I have an arduino sketch, that listens for RFID tags, and gets their uid's and stores them in an array of uint32_t
This is an arduino_uno project with an adaFruit BTLE and as adafruit NFC/RFID Shield
The array is initiated like so:
uint32_t items[]= { 0,0,0,0,0,0};
Then in my loop();
I find an id like so:
success = nfc1.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);
//
Serial.println(success,DEC);
if (success) {
// Display some basic information about the card
//Serial.println("Found an ISO14443A card");
//Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
//Serial.print(" UID Value: ");
nfc1.PrintHex(uid, uidLength);
if (uidLength == 4)
{
// We probably have a Mifare Classic card ...
cardid = uid[0];
cardid <<= 8;
cardid |= uid[1];
cardid <<= 8;
cardid |= uid[2];
cardid <<= 8;
cardid |= uid[3];
Serial.print("Seems to be a Mifare Classic card #");
Serial.println(cardid);
BTLEserial.print(cardid);
}
Serial.println("");
}
Not that that block of code prints out to the Serial Monitor this:
Seems to be a Mifare Classic card #347161076
Writing out
to BTLE: 0x31 0x36 0x38 0x38 0x34
But the BTLE app is seeing
16884
" as the cardid?
It seems obvious that this is do to some weird byte conversion on the uint32_tbeing handled by the BTLEserial.print() method.
As i find id's I am storeing up to six of them in the items array above. I would like to send that entire array via blue tooth to my device, as a comma separated string.
Please help convert this uint32_t to either a string or other object that can be handled by the BTLE
I figured it out by using this method:
int radix =10;
char buffer[33];
char* getStringForUI32_T(uint32_t value){
return ultoa(value,buffer,radix);
}
Related
I'm trying to set a unique id to each esp32 automatically. Before I was programming the devices using the ESP-IDF Framework that provides the method
esp_efuse_mac_get_default() this will return a 8 byte value unique over all devices I had my hands on.
In the arduino ide all I see is the ESP.getEfuseMac() method. This only returns 6 bytes and is the same for all devices of the same batch (?).
Is there any way I can get a 8 byte UUID on a ESP32?
Libraries like ArduinoUniqueID also use the ESP.getEfuseMac() and thus are not usable.
getEfuseMac returns a 64 bit integer.
uint64_t EspClass::getEfuseMac(void)
{
uint64_t _chipmacid = 0LL;
esp_efuse_mac_get_default((uint8_t*) (&_chipmacid));
return _chipmacid;
}
It should return it's MAC address which is unique to all esp.
On the ESP32 both ESP.getEfuseMac() and ESP.getChipId() returns the same MAC address.
Test it with:
Serial.printf("\nCHIP MAC: %012llx\n", ESP.getEfuseMac());
Serial.printf("\nCHIP MAC: %012llx\n", ESP.getChipId());
Or you could do this:
uint32_t low = ESP.getEfuseMac() & 0xFFFFFFFF;
uint32_t high = ( ESP.getEfuseMac() >> 32 ) % 0xFFFFFFFF;
uint64_t fullMAC = word(low,high);
Serial.printf("Low: %d\n",low);
Serial.printf("High: %d\n",high);
Serial.printf("Full: %d\n",fullMAC);
You can also use IDF functions in Arduino because it was built on it.
Check this:
void print_mac(const unsigned char *mac) {
printf("%02X:%02X:%02X:%02X:%02X:%02X\n", mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
}
void macTest(){
unsigned char mac_base[6] = {0};
esp_efuse_mac_get_default(mac_base);
esp_read_mac(mac_base, ESP_MAC_WIFI_STA);
unsigned char mac_local_base[6] = {0};
unsigned char mac_uni_base[6] = {0};
esp_derive_local_mac(mac_local_base, mac_uni_base);
printf("Local Address: ");
print_mac(mac_local_base);
printf("\nUni Address: ");
print_mac(mac_uni_base);
printf("MAC Address: ");
print_mac(mac_base);
}
void setup(){
Serial.begin(115200);
delay(500);
macTest();
}
I am using Arduino UNO and a PN532 NFC module to receive P2P NDEF messages from an Android phone.
I am sending a plaintext string "Hello". When the transfer is successful, I get this on my Arduino:
image
How can I extract the string "Hello" (I think the pairs of numbers before it is the "Hello" in hexadecimal, same for the "text/plain" type indication, type length and payload length) from the NDEF message payload into a regular variable?
Here is my Arduino code:
// Receive a NDEF message from a Peer
// Requires SPI. Tested with Seeed Studio NFC Shield v2
#include "SPI.h"
#include "PN532_SPI.h"
#include "snep.h"
#include "NdefMessage.h"
PN532_SPI pn532spi(SPI, 10);
SNEP nfc(pn532spi);
uint8_t ndefBuf[128];
void setup() {
Serial.begin(9600);
Serial.println("NFC Peer to Peer Example - Receive Message");
}
void loop() {
Serial.println("Waiting for message from Peer");
//string payload = nfc.read();
int msgSize = nfc.read(ndefBuf, sizeof(ndefBuf));
NdefMessage msg = NdefMessage(ndefBuf, msgSize);
msg.print();
}
A NdefMessage is made up of multiple NdefRecord items and you msg has 1 record
so this should do it (not tested)
// Get the first record
NdefRecord record = msg.getRecord(0);
// Get the payload size
byte length = record.getPayloadLength();
// Create byte array big enough for payload
byte payload[length];
// Get payload to byte array
record.getPayload(payload);
// Convert byte Array to string
String string = String((char *)payload);
I'm trying to use the MSPF5529 with my mac. I've downloaded code composer studio and can easily access the chip as well as blink lights and any other application I need.
The goal is for me to print a message using UART through serial communication on my Mac. I am currently using an application called "goSerial" in order to communicate with the chip. My code below initializes UART, takes in a single character, and then it is supposed to print out a character, and then blink a light. However, instead, the code takes in the character, and prints out a strange symbol, called a spacing cedilla, with a hex value of 0xFC, and then blinks the light.
This symbol appears regardless of which character I put into the MSP430 buffer.
My code is listed below. Has anyone had this problem before? How do I solve this?
void Init_UART(void);
void OUTA_UART(unsigned char A);
unsigned char INCHAR_UART(void);
#include "msp430f5529.h"
#include "stdio.h"
int main(void){
volatile unsigned char a;
volatile unsigned int i;
WDTCTL = WDTPW + WDTHOLD;
Init_UART();
a=INCHAR_UART();
a=INCHAR_UART();
OUTA_UART(a);
// go blink the light to indicate code is running
P1DIR |= 0x01;
for (;;){
P1OUT ^= 0x01; i = 10000;
do i--;
while (i != 0); }
}
void OUTA_UART(unsigned char A){
while ((UCA1STAT&UCBUSY));
// send the data to the transmit buffer
UCA1TXBUF =A;
}
unsigned char INCHAR_UART(void){
while ((UCA1STAT&UCBUSY) == 0);
// go get the char from the receive buffer
return (UCA1RXBUF);
}
void Init_UART(void){
P4SEL |= 0x30; // Port 4.4 and port 4.5 controls the transfer
UCA1CTL1|= UCSWRST; // Put state machine in reset
UCA1CTL1|= UCSSEL_1; //Choose 32765Hz
UCA0BR0=3; // Baud rate = 9600
UCA0BR1=0; // Choose 32765 hz
UCA1MCTL=0x06; // Modulation UCBRSx=3, UCBFx = 0
UCA1CTL1 &= ~UCSWRST; // Put USCI in operation mode
}
The UCBUSY flag is not very useful, and cannot be used like this.
That a byte has been received is indicated by UCRXIFG:
while (!(UCA1IFG & UCRXIFG)) ;
return UCA1RXBUF;
That a byte can be sent is indicated by UCTXIFG:
while (!(UCA1IFG & UCTXIFG)) ;
UCA1TXBUF = a;
I'm using the following code to successfully read IDs from MIFARE cards to the serial monitor.
#include <SPI.h>
#include <MFRC522.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
int readflag;
byte readCard[4];
#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance.
///////////////////////////////////////// Setup ///////////////////////////////////
void setup() {
Serial.begin(9600);
SPI.begin();
mfrc522.PCD_Init();
mfrc522.PCD_SetAntennaGain(mfrc522.RxGain_max);
lcd.begin(20, 4);
}
///////////////////////////////////////////////////////////////////////////////
// Main loop
///////////////////////////////////////////////////////////////////////////////
void loop () {
do {
readflag = checkread();
}
while (!readflag);
//If card detected do this
recordid();
}
///////////////////////////////////////////////////////////////////////////////
// Stores the ID of the card that's been detected in readCard byte array
///////////////////////////////////////////////////////////////////////////////
void recordid() {
mfrc522.PICC_IsNewCardPresent();
mfrc522.PICC_ReadCardSerial();
lcd.clear();
for (int i = 0; i < 4; i++) {
readCard[i] = mfrc522.uid.uidByte[i];
Serial.print( mfrc522.uid.uidByte[i], HEX);
}
Serial.println("");
mfrc522.PICC_HaltA();
}
/////////////////////////////////////////////
// Returns 1 if a card has been detected
/////////////////////////////////////////////
int checkread() {
if ( ! mfrc522.PICC_IsNewCardPresent()) {
return 0; } //no card detected
mfrc522.PICC_HaltA();
return 1; } //card detected
I have 12 cards and the serial monitor is telling me that their ID's are (hex):
3278CE3F
F5C9FD29
2FC640
82BA7A3F
2BD7A3F
52B77A3F
B2E5640
F2DD640
E2ECCC3F
22B3640
2FD640
73D5B7AC
I understand these are being stored in the readCard byte array.
I would like to compare the current value of this byte array to a known value to determine whether an instruction is run (e.g. a blink of an LED)
Something like this:
If (readCard = 2FD640) {
turn on LED
}
I have been able to do this successfully using this if statement:
if ( (uint32_t)readCard == 0x3FCE7832)
for example card one. However, it will not work with the cards with IDs that are not 8 digits long i.e. card 11 (2FD640).
Can anyone help me implement this in code?
Many thanks.
I dont know why if ( (uint32_t)readCard == 0x3FCE7832) worked for you; it shouldnt, since you are casting a byte pointer to a 32-bit integer. What you should have done is:
Declare readCard as a uint8_t pointer and not byte
The comparison should be like this: if (*((uint32_t *)readCard) == 0x3FCE7832)
But like you said, this wont work for the 11th card. You have to right-pad the reversed literal with zeros, like this: if (*((uint32_t *)readCard) == 0x40D62F00). To obtain the reversed literal (e.g. 0x2FDD640), write out the complete byte left padded with zeros to make 8 digits (e.g. 0x02FDD640). Then reverse the order of the bytes (e.g. 0x40D6FD02).
You could also store the card UIDs as arrays in your code and compare them byte-by-byte so that there is no dependence on the size of the UID to create 32-bit ints.
You could use a union like this:
union
{
byte Bytes[4];
uint32_t Integer;
} UnionCard;
Use it like this:
UnionCard Uc;
Fill it similar to your readCard[i] in the loop like this:
Uc.Bytes[i] = mfrc522.uid.uidByte[i];
Get the UInt with:
Uc.Integer;
I'm having some trouble understanding I2C. This is my first time using the protocol. The documentation says the following
I just don't know if I am supposed to write to a read register and the two bytes are 0x00 and 0x01, or use Wire.request to request two bytes.
I have read registers from 0-20 and several write registers however I'm only interested in the read registers.
Any help would be much appreciated and please ask any questions you might have.
Thanks,
Peter
EDIT
#include <Wire.h>
void setup() {
// put your setup code here, to run once:
Wire.begin();
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
int k = readRegister(0x08, 0x06);
Serial.println(k);
delay(500);
}
uint16_t readRegister(uint8_t i2cAddr, uint8_t regAddr) {
// I2C write sequence to address the given read register
Wire.beginTransmission(i2cAddr); // Module address
Wire.write(regAddr); // Register Address
Wire.write(0); // Command Data = dummy zeroes
Wire.write(0);
Wire.write(regAddr); // Checksum
Wire.endTransmission(); // Finish I2C write sequence
// I2C read sequence to actually get the register value
Wire.requestFrom(i2cAddr, 3);
uint16_t regVal = Wire.read();
regVal <<= 8;
regVal |= Wire.read();
if (Wire.read() == (((regVal >> 8) + regVal) & 0xFF)) {
return regVal; // Checksum OK
}
return 0xFFFF; // Checksum error
}
It seems the only way to say which register you want to read is to complete an I2C write sequence using that register's address. Probably the "Command Data" you use in the write sequence will be irrelevant if you use the address of a read register.
So it would become something like this:
uint16_t readRegister(uint8_t i2cAddr, uint8_t regAddr) {
// I2C write sequence to address the given read register
Wire.beginTransmission(i2cAddr); // Module address
Wire.write(regAddr); // Register Address
Wire.write(0); // Command Data = dummy zeroes
Wire.write(0);
Wire.write(-regAddr); // Checksum
Wire.endTransmission(); // Finish I2C write sequence
// I2C read sequence to actually get the register value
Wire.requestFrom(i2cAddr, 3);
uint16_t regVal = Wire.read();
regVal <<= 8;
regVal |= Wire.read();
if ((Wire.read() + regVal >> 8 + regVal & 0xFF) == 0) {
return regVal; // Checksum OK
}
return 0xFFFF; // Checksum error
}
It is usual in many chips to access subsequent register addresses incrementally by just issuing new read sequences. This way you could do a bulk or multi-byte read. However I'm not sure that's the case here, so you might need to do the write sequence every time.