MFRC522 and specific sector/block reading - arduino

I am creating a game using the Mifare tags embedded in 8 different playing pieces. I will be using an Arduino NANO with the MFRC522 (library https://github.com/miguelbalboa/rfid) to do the actual reading of the tags, and am using an ER301 reader/writer (with eReader software) to assign playing piece numbers to them. I will be creating multiples of each piece to head off any issues I would have with loss due to breakage or theft (due to these being rather unique playing pieces). Since there will be 8 different pieces, and 4 copies of each piece, that would be 32 UIDs to keep up with. I would rather assign a different number to each of pieces, and the same number of each piece to its duplicates - so only 8 numbers to keep up with.
My question is - how do I read a certain block and sector with the MFRC522?
Specifically, sector 2, block 8 - because this is where the Hex equivalent of the playing piece number shows up (when it is assigned as a Product Name with the eReader software and the ER301 writer). I understand using the library for the MFRC522 to read the UID, but this is a bit more in-depth than my understanding.
I have written several Sketches for the Arduino, but this is my foray into the world of RFID, and is quite a bit more extensive than my previous Arduino projects. Once I can read the specific sector & block, the Arduino NANO will output a binary representation (on 4 of the digital I/Os) of which playing piece was placed.

The library you are using provides dedicated methods to perform read and write operations on MIFARE tags:
StatusCode MIFARE_Read(byte blockAddr, byte *buffer, byte *bufferSize);
StatusCode MIFARE_Write(byte blockAddr, byte *buffer, byte bufferSize);
Since your description (sector 2, block 8) suggests that you are using MIFARE Classic tags, you would also need to authenticate to the tag in order to perform read/write operations. Thus, you would also need the authentication method:
StatusCode PCD_Authenticate(byte command, byte blockAddr, MIFARE_Key *key, Uid *uid);
Just as you would use the library to read the UID
if (mfrc522.PICC_ReadCardSerial()) {
Serial.print(F("Card UID:"));
dump_bytes(mfrc522.uid.uidByte, mfrc522.uid.size);
}
you could also access these read/write methods:
MFRC522::StatusCode status;
MFRC522::MIFARE_Key key;
byte buffer[18];
byte size = sizeof(buffer);
for (byte i = 0; i < MFRC522::MF_KEY_SIZE; ++i) {
key.keyByte[i] = 0xFF;
}
if (mfrc522.PICC_ReadCardSerial()) {
status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 8, &key, &(mfrc522.uid));
if (status == MFRC522::STATUS_OK) {
status = mfrc522.MIFARE_Read(8, buffer, &size);
if (status == MFRC522::STATUS_OK) {
Serial.print(F("Data (block = 8): "));
dump_bytes(buffer, 16);
}
}
}
Note that I assume block 8 (= sector 2, block 0) to be readbale using key A and that key A is set to the default transport key FF FF FF FF FF FF. If your other reader changed those values, you need to adapt the code accordingly. Moreover I used the pseudo-method dump_bytes(array, length) to indicate that the interesting value is the first length bytes of array. An implementation that actually prints those values is up to you.
Btw. a full example on how to use the library for read/write operations actually ships together with the library!. So you could just take a look at ReadAndWrite.ino on how to use that library.

Related

Sending 20-byte characteristic values with CurieBLE

The documentation for Arduino/Genuino 101's CurieBLE library states the following, in the section "Service Design Patterns":
A characteristic value can be up to 20 bytes long. This is a key
constraint in designing services. [...] You could also combine readings into a single characteristic, when a given sensor or actuator has multiple values associated with it.
[e.g. Accelerometer X, Y, Z => 200,133,150]
This is more efficient, but you need to be careful not to exceed the 20-byte limit. The accelerometer characteristic above, for example, takes 11 bytes as a ASCII-encoded string.
However, the typed Characteristic constructors available in the API are limited to the following:
BLEBoolCharacteristic
BLECharCharacteristic
BLEUnsignedCharCharacteristic
BLEShortCharacteristic
BLEUnsignedShortCharacteristic
BLEIntCharacteristic
BLEUnsignedIntCharacteristic
BLELongCharacteristic
BLEUnsignedLongCharacteristic
BLEFloatCharacteristic
BLEDoubleCharacteristic
None of these types of Characteristics appear to be able to hold a 20-byte string. (I have tried the BLECharCharacteristic, and it appears to pertain to a single char, not a char array.)
Using CurieBLE, how does one go about using a string as a characteristic value, as described in the documentation as an efficient practice?
Yours issue described here in official arduino 101 example. Few strings of code how to set an array:
BLECharacteristic heartRateChar("2A37", // standard 16-bit characteristic UUID
BLERead | BLENotify, 2);
...
const unsigned char heartRateCharArray[2] = { 0, (char)heartRate };
heartRateChar.setValue(heartRateCharArray, 2);
As you can see characteristic's value set using "setValue" function with desired array as an argument. You can pass a String as char* pointing to an array.

Reading a long text from GPRS Shield with Arduino

I am having hell with this and I know it is probably really simple. I am trying to read a text message from my Seeed GPRS shield. I have the shield setup as a software serial and I am displaying the information received from the GPRS to the serial monitor. I am currently sending all AT commands over serial while I work on my code. To display the data from the software serial to the serial monitor, I am using the following code.
while(GPRS.available()!=0) {
Serial.write(GPRS.read());
}
GPRS is my software serial obviously. The problem is, the text is long and I only get a few characters from it. Something like this.
+CMGR: "REC READ","1511","","13/12/09,14:34:54-24" Welcome to TM eos8
This text is a "Welcome to T-Mobile" text that is much longer. The last few characters shown are scrambled. I have done some research and have seen that I can mod the serial buffer size to 256 instead of the default 64. I want to avoid this because I am sure there is an easier way. Any ideas?
Have you tried reading into a character array, one byte at a time? See if this helps:
if (GPRS.available()) { // GPRS talking ..
while(GPRS.available()) { // As long as it is talking ..
buffer[count++]=GPRS.read();     
// read char into array
if(count == 64) break; // Enough said!
}
Serial.write(buffer,count); // Display in Terminal
clearBufferArray();
count = 0;
}
You need to declare the variables 'buffer' and 'count' appropriately and define the function 'clearBufferArray()'
Let me know if this helps.
Looks like this is simply the result of the lack of flow control in all Arduino serial connections. If you cannot pace your GPRS() input byte sequence to a rate that guarantees the input FIFO can't overflow, then your Serial.write() will block when the output FIFO fills. At that point you will be dropping new GPRS input bytes on the floor until Serial output frees up more space.
Since the captured output is apparently clean up to about 64 bytes, this suggests
a) a 64 byte buffer,
b) a GPRS data rate much higher than the Serial one, and
c) that the garbage data is actually the occasional valid byte from later in the sequence.
You might confirm this by testing the return code from Serial.write. If you get back zero, that byte is getting lost.
If you were using 9600 for Serial and 57600 for GPRS, I would expect somewhat more than 64 bytes to come through before the output gets mangled, but if the GPRS rate is more than 64x the Serial rate, the entire output FIFO could fill up within a single output byte transmission time.
Capturing to an intermediate buffer should resolve your issue, as long as it is large enough for the whole message. Similarly, extending the size of either the source (in conjunction with testing the Serial.write) or destination (without any additional code) FIFOs to the maximum datagram size should work.
I've had the same problem trying to read messages and get 64 characters. I overcame it by adding a "delay(10)" in the loop calling the function that does the read from the GPRS. Seems to be enough to overcome the race scenario. - Using Arduino Mega.
void loop() {
ReadmyGPRS();
delay(10); //A race condition exists to get the data.
}
void ReadmyGPRS(){
if (Serial1.available()){ // if data is comming from GPRS serial port
count = 0; // reset counter
while(Serial1.available()) // reading data into char array
{
buffer[count++]=Serial1.read(); // writing data into array
if(count == 160)break;
}
Serial.write(buffer,count);
}
}

Using ElectricImp server.show() and Arduino

I'm following the sparkfun tutorial for connecting an arduino to electric imp. I only have one arduino and imp, so I'm trying to get whatever I type in the arduino serial monitor to display in the imp node using server.show().
I've modified one of the functions in the sparkfun code to look like this:
function pollUart()
{
imp.wakeup(0.00001, pollUart.bindenv(this)); // schedule the next poll in 10us
local byte = hardware.uart57.read(); // read the UART buffer
// This will return -1 if there is no data to be read.
while (byte != -1) // otherwise, we keep reading until there is no data to be read.
{
// server.log(format("%c", byte)); // send the character out to the server log. Optional, great for debugging
// impeeOutput.set(byte); // send the valid character out the impee's outputPort
server.show(byte)
byte = hardware.uart57.read(); // read from the UART buffer again (not sure if it's a valid character yet)
toggleTxLED(); // Toggle the TX LED
}
}
server.show(byte) is only displaying seemingly random numbers. I have an idea of why this is, I just don't know how to fix it because I'm not that familiar with UARTs and squirrel.
local byte = hardware.uart57.read(); reads in the ascii characters from the arduino in byte form (I think), and they're not being 'translated' into their ascii characters before I use server.show(byte).
How do I do this in squirrel?
Also, I think polling every 10us is the wrong way to go here. I'd like to only poll when there's new information, but I also don't know how to do that in squirrel. Can someone point me to an example where this happens?
Thanks!
I think you are passing the wrong data type to the show method of the server object. The electric imp docs state that it takes a string, server.show(string). I think that local is the correct type to receive the value from hardware.uart57.read(). You can tell from the docs as well. So, you need to find a way to cast your byte to a string. I bet you could find the answer here. From what I read Squirrel use's Unicode so there is a probably a function that takes Unicode bytes and loads them into a string object.

Simple algorithm for reliable communications

So, I have worked on large systems in the past, like an iso stack session layer, and something like that is too big for what I need, but I do have some understanding of the big picture. What I have now is a serial point to point communications link, where some component is dropping data (often).
So I am going to have to write my own, reliable delivery system using it for transport. Can someone point me in the directions for basic algorithms, or even give a clue as to what they are called? I tried a Google, but end up with post graduate theories on genetic algorithms and such. I need the basics. e.g. 10-20 lines of pure C.
XMODEM. It's old, it's bad, but it is widely supported both in hardware and in software, with libraries available for literally every language and market niche.
HDLC - High-Level Data Link Control. It's the protocol which has fathered lots of reliable protocols over the last 3 decades, including the TCP/IP. You can't use it directly, but it is a template how to develop your own protocol. Basic premise is:
every data byte (or packet) is numbered
both sides of communication maintain locally two numbers: last received and last sent
every packet contains the copy of two number
every successful transmission is confirmed by sending back an empty (or not) packet with the updated numbers
if transmission is not confirmed within some timeout, send again.
For special handling (synchronization) add flags to the packet (often only one bit is sufficient, to tell that the packet is special and use). And do not forget the CRC.
Neither of the protocols has any kind of session support. But you can introduce one by simply adding another layer - a simple state machine and a timer:
session starts with a special packet
there should be at least one (potentially empty) packet within specified timeout
if this side hasn't sent a packet within the timeout/2, send an empty packet
if there was no packet seen from the other side of communication within the timeout, the session has been termianted
one can use another special packet for graceful session termination
That is as simple as session control can get.
There are (IMO) two aspects to this question.
Firstly, if data is being dropped then I'd look at resolving the hardware issues first, as otherwise you'll have GIGO
As for the comms protocols, your post suggests a fairly trivial system? Are you wanting to validate data (parity, sumcheck?) or are you trying to include error correction?
If validation is all that is required, I've got reliable systems running using RS232 and CRC8 sumchecks - in which case this StackOverflow page probably helps
If some components are droping data in a serial point to point link, there must exist some bugs in your code.
Firstly, you should comfirm that there is no problem in the physical layer's communication
Secondly, you need some konwledge about data communication theroy such like ARQ(automatic request retransmission)
Further thoughts, after considering your response to the first two answers... this does indicate hardware problems, and no amount of clever code is going to fix that.
I suggest you get an oscilloscope onto the link, which should help to determine where the fault lies. In particular look at the baud rate of the two sides (Tx, Rx) to ensure that they are within spec... auto-baud is often a problem?!
But look to see if drop out is regular, or can be sync-ed with any other activity.
on the sending side;
///////////////////////////////////////// XBee logging
void dataLog(int idx, int t, float f)
{
ubyte stx[2] = { 0x10, 0x02 };
ubyte etx[2] = { 0x10, 0x03 };
nxtWriteRawHS(stx, 2, 1);
wait1Msec(1);
nxtWriteRawHS(idx, 2, 1);
wait1Msec(1);
nxtWriteRawHS(t, 2, 1);
wait1Msec(1);
nxtWriteRawHS(f, 4, 1);
wait1Msec(1);
nxtWriteRawHS(etx, 2, 1);
wait1Msec(1);
}
on the receiving side
void XBeeMonitorTask()
{
int[] lastTick = Enumerable.Repeat<int>(int.MaxValue, 10).ToArray();
int[] wrapCounter = new int[10];
while (!XBeeMonitorEnd)
{
if (XBee != null && XBee.BytesToRead >= expectedMessageSize)
{
// read a data element, parse, add it to collection, see above for message format
if (XBee.BaseStream.Read(XBeeIncoming, 0, expectedMessageSize) != expectedMessageSize)
throw new InvalidProgramException();
//System.Diagnostics.Trace.WriteLine(BitConverter.ToString(XBeeIncoming, 0, expectedMessageSize));
if ((XBeeIncoming[0] != 0x10 && XBeeIncoming[1] != 0x02) || // dle stx
(XBeeIncoming[10] != 0x10 && XBeeIncoming[11] != 0x03)) // dle etx
{
System.Diagnostics.Trace.WriteLine("recover sync");
while (true)
{
int b = XBee.BaseStream.ReadByte();
if (b == 0x10)
{
int c = XBee.BaseStream.ReadByte();
if (c == 0x03)
break; // realigned (maybe)
}
}
continue; // resume at loop start
}
UInt16 idx = BitConverter.ToUInt16(XBeeIncoming, 2);
UInt16 tick = BitConverter.ToUInt16(XBeeIncoming, 4);
Single val = BitConverter.ToSingle(XBeeIncoming, 6);
if (tick < lastTick[idx])
wrapCounter[idx]++;
lastTick[idx] = tick;
Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() => DataAdd(idx, tick * wrapCounter[idx], val)));
}
Thread.Sleep(2); // surely we can up with the NXT
}
}

OpenCL device uniqueness

Is there a way to get OpenCL to give me a list of all unique physical devices which have an OpenCL implementation available? I know how to iterate through the platform/device list but for instance, in my case, I have one Intel-provided platform which gives me an efficient device implementation for my CPU, and the APP platform which provides a fast implementation for my GPU but a terrible implementation for my CPU.
Is there a way to work out that the two CPU devices are in fact the same physical device, so that I can choose the most efficient one and work with that, instead of using both and having them contend with each other for compute time on the single physical device?
I have looked at CL_DEVICE_VENDOR_ID and CL_DEVICE_NAME but they don't solve my issues, the CL_DEVICE_NAME will be the same for two separate physical devices of the same model (dual GPU's) and CL_DEVICE_VENDOR_ID gives me a different ID for my CPU depending on the platform.
An ideal solution would be some sort of unique physical device ID, but I'd be happy with manually altering the OpenCL configuration to rearrange the devices myself (if such a thing is possible).
As far as I could investigate the issue now, there is no reliable solution. If all your work is done within a single process, you may use the order of entries returned by clGetDeviceIDs or cl_device values themselves (essentially they're pointers), but things get worse if you try to share those identifiers between processes.
See that guy's blog post about it, saying:
The issue is that if you have two identical GPUs, you can’t distinguish between them. If you call clGetDeviceIDs, the order in which they are returned is actually unspecified, so if the first process picks the first device and the second takes the second device, they both may wind up oversubscribing the same GPU and leaving the other one idle.
However, he notes that nVidia and AMD provide their custom extensions, cl_amd_device_topology and cl_nv_device_attribute_query. You may check whether these extensions are supported by your device, and then use them as the following (the code by original author):
// This cl_ext is provided as part of the AMD APP SDK
#include <CL/cl_ext.h>
cl_device_topology_amd topology;
status = clGetDeviceInfo (devices[i], CL_DEVICE_TOPOLOGY_AMD,
sizeof(cl_device_topology_amd), &topology, NULL);
if(status != CL_SUCCESS) {
// Handle error
}
if (topology.raw.type == CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD) {
std::cout << "INFO: Topology: " << "PCI[ B#" << (int)topology.pcie.bus
<< ", D#" << (int)topology.pcie.device << ", F#"
<< (int)topology.pcie.function << " ]" << std::endl;
}
or (code by me, adapted from the above linked post):
#define CL_DEVICE_PCI_BUS_ID_NV 0x4008
#define CL_DEVICE_PCI_SLOT_ID_NV 0x4009
cl_int bus_id;
cl_int slot_id;
status = clGetDeviceInfo (devices[i], CL_DEVICE_PCI_BUS_ID_NV,
sizeof(cl_int), &bus_id, NULL);
if (status != CL_SUCCESS) {
// Handle error.
}
status = clGetDeviceInfo (devices[i], CL_DEVICE_PCI_BUS_ID_NV,
sizeof(cl_int), &slot_id, NULL);
if (status != CL_SUCCESS) {
// Handle error.
}
std::cout << "Topology = [" << bus_id <<
":"<< slot_id << "]" << std::endl;
If you have two devices of the exact same kind belonging to a platform, you can tell them apart by the associated cl_device_ids return by clGetDeviceIDs.
If you have devices that can be used by two different platforms you can eliminate the entries for the second platform by comparing the device names from CL_DEVICE_NAME.
If you want to find the intended platform for a device, compare the CL_PLATFORM_VENDOR and CL_DEVICE_VENDOR strings from clGetPlatformInfo() and clGetDeviceInfo respectively.
You can read in all platforms and all their associated devices into separate platform-specific lists and then eliminate doubles by comparing the device names in the separate lists. This should ensure that you do not get the same device for different platforms.
Finally you can, by command line arguments or configuration file for example, give arguments to your application to associate devices of a certain type (CPU, GPU, Accelerator) with a specific platform if there exists a choice of different platforms for a device type. Hopefully this will answer your question.
anyway let's just assume that you are trying to pull the unique id for all devices, actually you can just simply query with clGetDeviceIDs:
cl_int clGetDeviceIDs(cl_platform_id platform,
cl_device_type device_type,
cl_uint num_entries,
cl_device_id *devices,
cl_uint *num_devices)
then your list of device will be inserted to the *devices array, and then you can do clGetDeviceInfo() to find out which device you'd like to use.
Combining answers above, my solution was:
long bus = 0; // leave it 0 for Intel
// update bus for NVIDIA/AMD ...
// ...
long uid = (bus << 5) | device_type;
Variable bus was computed according NVIDIA/AMD device-specific info queries, as mentioned firegurafiku, variable device_type was result of clGetDeviceInfo(clDevice, CL_DEVICE_TYPE, sizeof(cl_device_type), &device_type, nullptr) API call, as Steinin suggested.
Such approach solved issue of having equal unique ID for Intel CPU with integrated GPU. Now both devices have unique identifiers, thank to different CL_DEVICE_TYPE's.
Surprizingly, the case of running code on Oclgrind-emulated device, Oclgrind simulator device also gets unique identifier 15, disctinct from any other on my system.
The only case when proposed approach can fail - several CPUs of same model on a single mainboard.

Resources