Windows 10 IOT - RFID RC522 Read UID 7 byte - c#

i'm try to develop Project RFID Reader in windows 10 IOT in c#
i'm use RFID sticker buy from china. refer link below
https://www.aliexpress.com/item-img/10-NFC-13-56-NTAG-213-RFID/32709729334.html
and i'm use example from like below
RFID RC522 Raspberry PI 2 Windows IOT
During test RFID reader. it's work to read UID 4 byte.but i'm try to read 7 byte UID. It 's not working to read.
i'm modify some part of RC522 RFID
internal Uid(byte[] uid)
{
FullUid = uid;
//================ Change to 7 byte ======================
Bcc = uid[7];
Bytes = new byte[7];
System.Array.Copy(FullUid, 0, Bytes, 0, 7);
//Bcc = uid[4];
//Bytes = new byte[4];
//System.Array.Copy(FullUid, 0, Bytes, 0, 4);
foreach (var b in Bytes)
{
if (b != 0x00)
IsValid = true;
}
}
And
public Uid ReadUid()
{
// Run the anti-collision loop on the card
//Transceive(false , PiccCommands.Anticollision_1, PiccCommands.Anticollision_2);
Transceive(false, PiccCommands.Anticollision_1, PiccCommands.Anticollision_2);
// Return tag UID from FIFO
//return new Uid(ReadFromFifo(5));
return new Uid(ReadFromFifo(8));
}
it's still not reading.
So please advise.

There are RC522-based readers on the market that fail to read some IC cards, especially the ones with 7-byte UID. The problem is in slight differences in their antenna coil and capacitors.
The solution is either
to buy a "good" reader (which is hard to distinguish if you are buying it online)
or
to replace the capacitors C8 to C11 (C8+C9 150pF, C10+C11 33pF).
Here you can find a thorough analysis of the problem and the solution:
https://www.eluke.nl/2018/03/08/fixed-rc522-rfid-reader-not-reading-some-cards-part-1/

If the card is an S50 (aka Mifare 1K Classic) card type ISO14444A, they respond with 2Bytes (Cascade 1), 4Bytes (Cascade2) or 7Bytes (Cascade3) as their UID but you have to 'S'elect the card after starting the COM serial port. If, however you are using a reader that uses either ATR or ATS then you get back a string of hexadecimals that describe the card's characteristics. How do you know the difference - its in the documentation about the reader. Chinese cards typically are difficult to read off the starting block - try initialising a card using NFC on your mobile phone first, or just try reading the card with your phone - use TagWriter available on Google Play. Additionally look up the standards for ISO1444A cards - ISO15693 are similar but not the same. Also look at https://lastminuteengineers.com/how-rfid-works-rc522-arduino-tutorial/

Related

How to receive single bytes from usb serial device in Android

I am writing an android app in c# (using Avalonia) to communicate with my embedded usb device. The device has an atxmega microcontroller and utilises the atmel provided cdc usb driver. I have a desktop version of the app using System.IO.Ports.SerialPort. I use SerialPort.Write() to write data and SerialPort.ReadByte() in a loop to read data - using SerialPort.Read() and trying to read multiple bytes very often fails, while the looped byte by byte reading basically never does. It works on both Windows and Mac pcs.
The communication is very straightforward - the host sends commands and expects a known length of data to come in from the device.
On the android app I am using the android.hardware.usb class and adapted the code from the multiple serial port wrappers for cdc devices. Here is my connect function:
public static bool ConnectToDevice()
{
if (Connected) return true;
UsbDevice myDevice;
if ((myDevice = GetConnectedDevice()) == null) return false;
if (!HasPermission(myDevice)) return false;
var transferInterface = myDevice.GetInterface(1);
var controlInterface = myDevice.GetInterface(0);
writeEndpoint = transferInterface.GetEndpoint(1);
readEndpoint = transferInterface.GetEndpoint(0);
deviceConnection = manager.OpenDevice(myDevice);
if (deviceConnection != null)
{
deviceConnection.ClaimInterface(transferInterface, true);
deviceConnection.ClaimInterface(controlInterface, true);
SendAcmControlMessage(0x20, 0, parameterMessage);
SendAcmControlMessage(0x22, 0x03, null); //Dtr Rts true
Connected = true;
OnConnect?.Invoke();
return true;
}
return false;
}
The two control transfers are what I borrowed from the serial port wrappers and I use them to:
Set the default parameters - 115200 baudrate, 1 stop bit, parity none, 8 data bits which is the same as in my embedded usb config. This doesn't seem necessary but I do it anyway. The response from the control transfer is 7, so I assume it works properly.
Set Dtr and Rts to true. This doesn't seem to be necessary either - the desktop code works with both set to false as well as to true. The control transfer response is 0 so I assume it also works properly.
I checked all endpoints and parameters after connection and they all seem to be correct - both read and write Endpoints are bulk endpoints with correct data direction.
Writing to my device is not a problem. I can use either the bulkTransfer method as well as UsbRequest and they both work perfectly.
Unfortunately everything falls apart when trying to read data. The initial exchange with the device is as follows:
Host sends a command and expects 4 bytes of data.
Host sends another command and expects 160 bytes of data.
The bulk transfer method looks like this:
public static byte[] ReadArrayInBulk(int length)
{
byte[] result = new byte[length];
int transferred = deviceConnection.BulkTransfer(readEndpoint, result, length, 500);
if (transferred != length)
{
transferred = deviceConnection.BulkTransfer(readEndpoint, result, length, 500);
}
return result;
}
The first transfer almost always (99.9%) returns 0 and then the second returns the proper data, up to a point. For the first exchange it does receive the 4 bytes correctly. However, for the second exchange, when it expects 160 bytes the second transfer returns 80, 77, 22 and other random lengths of data. I tried making a loop and performing bulk transfers until the number of bytes transferred is equal to the expected amount but unfortunately after receiving the random length of data for the first time the bulk transfer starts always returning 0.
So I tried the UsbRequest way to get the data:
public static byte[] GetArrayRequest(int length)
{
byte[] result = new byte[length];
UsbRequest req = new UsbRequest();
req.Initialize(deviceConnection, readEndpoint);
ByteBuffer buff = ByteBuffer.Wrap(result);
req.Queue(buff, length);
var resulting = deviceConnection.RequestWait();
if (resulting != null) buff.Get(result);
req.Close();
return result;
}
The WrapBuffer does get filled with the expected amount of data (the position is the same as length), unfortunately the data is all 0. It does work for a couple transfers once in a while, but 99% of the time it just returns zeroes.
So, given that the desktop version also has trouble reading data in bulk using the SerialPort.Read() method but works perfectly when reading them one by one (SerialPort.ReadByte() which underneath uses SerialPort.Read() for a single byte) in a loop I decided to try doing that in my app as well.
Unfortunately, when looping using the UsbRequest method not only does it take ages but it also always returns zeroes. When looping using the BulkTransfer method for a single byte array it returns 0 on the first transfer and -1 on the second, indicating a timeout.
I have spent so much time with this that I am at my wits' end. I checked multiple implementations of usb serial for android projects from mik3y, kai-morich, felHR85 but all they do differently from me are the two control transfers, which I have now added - to no avail.
Can anyone tell me what could cause the bulkTransfer to always return 0 in response to the first transfer (which is supposed to be a success, but what does it actually do with no data read?) and only return some data or timeout (in case of a single byte transfer) on the second one? If it were reliably doing so I would just get used to it, but unfortunately it only seems to work correctly for smaller transfers and only up to a certain point, because while the initial couple/couple dozen bytes are correct, then it stops receiving any more in random intervals. Or why the UsbRequest method does fill the buffers, but with only zeroes 99% of the time?

Windows 10 IOT SPI Chip Select with other Pins or GPIO'S

i have a question about windows 10 iot and the SPI communication. I try to communicate with an extension board for the Raspberry PI. To communicate with the board i use SPI0. The 1st slave is on GPIO 7 (Pin 26), the 2nd Chip Select is on GPIO 24 (Pin 18) and the 3rd is on GPIO 08 (Pin 24).
The Position from the Pins is fixed by the manufacturer, the system is originally for linux.
The communication with slave 1 (CS1) works very well. But that's all. My problem is to speak with the 2nd and 3rd Slave. I tryed to use the GPIO 24 as an Input/Output GPIO to set up the communication before Read from CS0 as an dummy but no chance.
At the moment, I am using a hardware hack. I am connecting PIN 18 to PIN 24 with a cable, however, I don't want to open each system to place a cable bridge.
Is there a possibility to setup an customized windows 10 iot image for the raspberry pi to use the Pin 26 as CS0, Pin 24 as CS1 and Pin 18 as CS2 ?
As #Rita Han points out, the on-board SPI controller does not support pin 18 multiplexing for SPI chip select. However, I think it's still quite possible using the Pin 18 as the CS pin if you hack the spi driver a little bit.
So the inbox SPI driver is located in here, https://github.com/ms-iot/bsp/tree/master/drivers/spi/bcm2836, if you look at the source code, you can see before and after every SPI data transfer, it's setting up the SPI register to toggle the chip select pin.
So what you can do in here is instead of using the default on-board spi driver, try using the GPIO controller to toggle the pin 18 voltage, in the inbox SPI driver.
The SPI chip select pin has slack timing requirement, so i think it should be OK to use the GPIO timing.
After which, you'll need to follow some tutorial to create custom windows iot image.
You just have to indicate the device to which you are calling.
First, set the configuration of the SPI for example, using chip select line 0
settings = new SpiConnectionSettings(0); //chip select line 0
settings.ClockFrequency = 1000000;
settings.Mode = SpiMode.Mode0;
String spiDeviceSelector = SpiDevice.GetDeviceSelector();
devices = await DeviceInformation.FindAllAsync(spiDeviceSelector);
_spi1 = await SpiDevice.FromIdAsync(devices[0].Id, settings);
You can not use this pin in further actions! So now you should configure the output ports using GpioPin class, which you will use to indicate the device.
GpioPin_19 = IoController.OpenPin(19);
GpioPin_19.Write(GpioPinValue.High);
GpioPin_19.SetDriveMode(GpioPinDriveMode.Output);
GpioPin_26 = IoController.OpenPin(26);
GpioPin_26.Write(GpioPinValue.High);
GpioPin_26.SetDriveMode(GpioPinDriveMode.Output);
GpioPin_13 = IoController.OpenPin(13);
GpioPin_13.Write(GpioPinValue.High);
GpioPin_13.SetDriveMode(GpioPinDriveMode.Output);
Always before transfer indicate device: (example method)
private byte[] TransferSpi(byte[] writeBuffer, byte ChipNo)
{
var readBuffer = new byte[writeBuffer.Length];
if (ChipNo == 1) GpioPin_19.Write(GpioPinValue.Low);
if (ChipNo == 2) GpioPin_26.Write(GpioPinValue.Low);
if (ChipNo == 3) GpioPin_13.Write(GpioPinValue.Low);
_spi1.TransferFullDuplex(writeBuffer, readBuffer);
if (ChipNo == 1) GpioPin_19.Write(GpioPinValue.High);
if (ChipNo == 2) GpioPin_26.Write(GpioPinValue.High);
if (ChipNo == 3) GpioPin_13.Write(GpioPinValue.High);
return readBuffer;
}

redirect input from keyboard like device to background process in windows environment

I use simple RFID reader device which connected to PC with usb cable and identified as keyboard like device.
I want to read input from this device by my application but it is running in background i.e. other application is in focus.
How can I redirect stdin to my application in windows 7 environment?
I can't change focus to my application
I can't make change in front application (e.g. catch stdin and send it to my application via pipe etc.)
My application is written in C# but I can rewrite it to Java / C
The PC runs Win 7 OS.
Thanks
y
Here my solution:
I have connected a normal Keyboard and a Card Reader via USB to my computer.
Both devices write to the windows keyboard buffer.
I want to redirect the input of the Card Reader to another application or file and remove it from the keyboard buffer (so that this input will not show up in any editor).
What I know / Prerequisites:
The input of the Card Reader only contains hexadecimal letters (0-9, A-F) and is finished by a newline.
The Card Reader input will be received "on-block", this means between two received letters there are only a few milliseconds
It is not possible for a human to enter two or more numbers within less than 70ms(I have tried it)
What I do:
I listen to the keyboard buffer and take out every single input letter/key. Any input which is not 0-9 or A-F will be put back to the keyboard buffer immediately.
If a input 0-9 or A-F comes up I will store it in a string buffer (it might be from the card reader)
If there is no further input for more than 70ms and there are at least 4 Bytes containing 0-9 or A-F in the buffer, then I assume/know it was from the Card Reader and use it in my own way. These Bytes have been already taken out of the keyboard buffer.
If there are only one/two/three letter(s) 0-9/A-F in my buffer, then after 70ms they will be put back to the windows keyboard buffer. While typing you can't realise that "some" letters show up a little postponed for a human being.
Here my program (written in the script language AutoHotkey):
KeybRedir.ahk
; KeybRedir
; Programmiert von Michael Hutter - Mai 2018
#NoEnv ;Avoids checking empty variables to see if they are environment variables
#SingleInstance force
Process, Priority, , Normal
#Warn All
SaveKeyList=
0::
1::
2::
3::
4::
5::
6::
7::
8::
9::
+A::
+B::
+C::
+D::
+E::
+F::
Return::
{ ; If one of these characters was typed => take it out of windows key buffer...
if A_ThisHotkey = Return
Hotkey:=Chr(13)
else
Hotkey:=A_ThisHotkey
SaveKeyList = %SaveKeyList%%Hotkey%
SetTimer , DoKeyPlay, 70 ; Wait 70ms for another key press of charlist (re-trigger the timer in case it already runs)
}
return
DoKeyPlay:
SetTimer , , Off
SaveText:=RegExReplace(SaveKeyList, "\+", "")
StringReplace, SaveText, SaveText, `r, , All
if StrLen(SaveText) < 4 ; Accumulated text size < 4 letters => normal key input
{
SendPlay %SaveKeyList% ; put captured text back in windows key buffer
}
else ; Now we have the input of the card reader
{
SplashTextOn, , , %SaveText% ; Do something with the input or the card reader ...
}
SaveKeyList=
SaveText=
SetTimer , SplashOff, 2000
return
SplashOff:
SplashTextOff
SetTimer , , Off
return
You can compile this script to a exe file (327KB) using the Autohotkey Compiler.

How to fix issue sending text to Arduino over bluetooth serial port from C#

I have an Arduino Uno with a Bluesmirf Silver module connected. My Arduino has a temperature sensor which records the temp regularly. The Arduino listens for any string being sent to it over bluetooth and responds with the latest data.
I have written a C# application to fetch this data but I am seeing some strange behaviour. I am using the following code to connect, send a string and get the returned data.
mPort = new SerialPort(mPortName, 115200, Parity.None, 8, StopBits.One);
mPort.Open();
mPort.Write("download");
Thread.Sleep(1000);
while (mPort.BytesToRead > 0)
{
String data = mPort.ReadExisting();
this.BeginInvoke(new Action<String>(AddMessage), data);
}
The data I get back looks like this:
Line added locally within C# application:
Send: download
Lines added based on data received from Arduino:
Read: d???+?
GotData
------
Total Readings, 1069
Num Readings, 360
Lost Readings, 709
Reading Interval, 240000
------
350,19.34
351,19.34
352,19.34
353,20.31
....
All the text looks fine apart from the string which is being echoed back which I sent to the Arduino. Have I done something wrong with the way I sent the data?
FYI - The datasheet for the bluetooth module is here: http://www.sparkfun.com/datasheets/Wireless/Bluetooth/rn-bluetooth-um.pdf
#Jeff - This is the code which I use on my Arduino to receive data: https://github.com/mchr3k/arduino/blob/master/tempsensor/StringReader.cpp
#Jeff - stringDataLen defines the length and I call the overall function from this file: https://github.com/mchr3k/arduino/blob/master/tempsensor/tempsensor.ino
EDIT: Here is the complete source code
Arduino - https://github.com/mchr3k/arduino/tree/master/tempsensor
C# application - https://github.com/mchr3k/arduino/tree/master/serialdownload
The C# code is definitely getting the flow control wrong for some reason. I have switched to use the following code in C# and this gets a string through without corruption.
private void write(SerialPort mPort, string str)
{
foreach (char c in str)
{
mPort.Write(new char[] {c}, 0, 1);
Thread.Sleep(10);
}
}
An incorrect encoding perhaps?
mPort = new SerialPort(mPortName, 115200, Parity.None, 8, StopBits.One);
mPort.Encoding = System.Text.Encoding.ASCII; // Or System.Text.Encoding.UTF8
mPort.Open();
mPort.Write("download");
Read byte-by-byte and check each byte one by one to debug lower level problems. ReadExisting() converts bytes to a String based on the Encoding property.
My issue was caused by me using the SoftwareSerial class to communicate with my Bluetooth module on pins 2 & 3. I was using a baud rate of 115200 which is claimed to be supported on this page: http://arduino.cc/en/Reference/SoftwareSerial
However, this page ( http://arduino.cc/en/Reference/SoftwareSerialBegin ) states that the maximum baud rate supported is actually 9600. I'm not sure whether this is accurate but reducing my baud rate to 9600 has fixed my issue.
I suggest you to decrease communication speed, because there is no reason to use 115200bps (only if your module demand this speed, then it's ok). Also you are sending string "download" which is not good, rather use markers something like "#D" which internally for your Arduino device means, send data to computer. In this way you are sending only two bytes instead eight, and you will decrease probability of error, and Arduino code will be better.
Now, let's try fix the problem. First try use something like this when you are reading data from Arduino device:
ArayList dataReceaved=new ArrayList():
while(serialPort.BytesToRead>0 && serialPort.IsOpen){
dataReceaved.Add(serialPort.ReadByte());
}
So I suggest you to read byte by byte, in this or similar way. Also you shold be careful if you are sending numbers from Arduino device. If you are, then use something like this:
Serial.print(temperatureValue,BYTE);
With this code you explicitly say that data you are sending is byte long. If this not help, please let me know, so we can try something else.

Does .NET 3.5 SP1 SerialPort class append extra 0's on transmission?

Update
Turns out the error was in the crypto processor code, that is fixed. But now running into what seems like it might be a handshaking issue.
On first transmission, we get a single byte back from the device with value 0xFF(don't know why, the engineer I'm working with isn't too experienced with RS-232 either). Then, things run as normal (just sending the device one byte at a time, and waiting for a matching echo). However, neither the device nor the .NET app can send more than a couple of bytes at a time before one of them locks up and refuses to send or receive.
At work I'm writing an app that interfaces over RS232 with a crypto processor inside a device to reprogram flash modules inside the device.
To just take things slow and make sure all our headers are right, we're writing one byte at a time with SerialPort.Write(). However, when we run the code on the crypto processor, it reads an extra NULL in between each byte. When I test the .NET code on my local machine with two serial ports and a crossover cable, I capture the output in HyperTerminal or Putty and there are no extra NULLs when I view the log in Notepad++.
However, to further complicate things, when we manually type messages byte-per-byte via HyperTerminal to the crypto processor, it reads the input as a single byte only, no extra NULLs (as compared to the .NET app). Anybody have any experience with .NET doing mysterious things when it writes to a SerialPort?
We're initializing a test chunk with this:
byte[] testBytes = new byte[] { (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', (byte)'H' };
byte[] byteArray = new byte[256];
for (int i = 0; i < 32; i++)
{
testBytes.CopyTo(byteArray, i * 8);
}
And sending it with this:
public void StutterSend(byte[] data, long delayMs)
{
bool interactive = false;
if (delayMs < 0)
interactive = true;
for (int i = 0; i < data.Length; i++)
{
serialPort.Write(data, i, 1);
if (interactive)
{
WriteLine("Sent byte " + (i + 1) + " of " + data.Length + ". Press any key to send moar.");
Console.ReadKey();
}
else
{
double timer = DateTime.Now.TimeOfDay.TotalMilliseconds;
do { } while ((DateTime.Now.TimeOfDay.TotalMilliseconds - timer) < delayMs);
}
}
WriteLine("Done sending bytes.");
}
Our SerialPort is configured with all the matching parameters (stop bits, data bits, parity, baud rate, port name), and our handshake is set to None (it's just how our uart driver works).
Regarding your update, it sounds like your crypto processor has some more problems. Getting a 0xff back can be the result of an unexpected glitch of <= 1 bit time on the Tx line of the RS232 port. This is interpreted as a start bit by the PC. After the glitch, the Tx line returns to the mark state and now that the UART on the PC has a start bit, it interprets the "data" bits as all ones (the value for the mark state). The mark state is also the correct value for the stop bit(s) so your PC's UART has received a valid byte with a value of 0xff. Note that the glitch can be very fast relative to the RS232 data rate and still be interpreted as a start bit so have your engineer look at this line with an oscilloscope in normal mode/single sequence trigger to confirm this.
What is the Encoding property for the serialPort set to? The docs for SerialPort.Write( byte[], int, int) say that it runs its data through an Encoder object (which doesn't really make sense to me for a byte[]). It's supposed to default to ASCIIEncoding, but it seems like it might be set to something else. try explicitly setting it to ASCIIEncoding and see if that helps. I can't recall if this was an issue for me back when I did some serial port stuff in .NET to talk to an embedded board...
Note that even with ASCIIEncoding in use, you'll get some (probably unwanted) transformation of data - if you try to send something above value 127, the encoder will convert it to '?' since it's not a valid ASCII character. I can't recall off the top of my head how I got the serial port to simply leave my data alone - I'll have to dig around in some source code...
SerialPort sets the Parity property to Parity.None if you don't specify any. This means in case your receiver expects a Partity bit, it will never get one as long as you don't tell SerialPort explicitely to send along a Parity Bit with the transmitted data.
And the fact that it went well on HyperTerminal could be that HyperTerminal uses a Parity bit by default ( I don't know HyperTerminal well).

Categories