AVR UART receives wrong bytes - avr-gcc

after a long pause I started to program AVRs again. I was able to setup a UART communication between my Linux computer and an Atmega8. Unfortunately the Atmega8 seems to receive the wrong bytes when I send bytes greater than 0x1f.
The UART is running with 9600 BAUD and the data format 8N1.
// clock frequency 1Mhz
#define F_CPU 1000000UL
// baud rate
#define BAUD 9600
#define BAUDRATE ((F_CPU)/(BAUD*16UL)-1)
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h>
void uart_init (void);
void uart_putc (unsigned char data);
void uart_puts (unsigned char * str, uint8_t size);
// interrupt service routine for UART receiver interupt
ISR(USART_RXC_vect) {
// get received char
unsigned char received_char = UDR;
uart_puts("received=", 9);
if((received_char & (1<<7)) == (1<<7)) {
uart_putc('1');
} else {
uart_putc('0');
}
if((received_char & (1<<6)) == (1<<6)) {
uart_putc('1');
} else {
uart_putc('0');
}
if((received_char & (1<<5)) == (1<<5)) {
uart_putc('1');
} else {
uart_putc('0');
}
if((received_char & (1<<4)) == (1<<4)) {
uart_putc('1');
} else {
uart_putc('0');
}
if((received_char & (1<<3)) == (1<<3)) {
uart_putc('1');
} else {
uart_putc('0');
}
if((received_char & (1<<2)) == (1<<2)) {
uart_putc('1');
} else {
uart_putc('0');
}
if((received_char & (1<<1)) == (1<<1)) {
uart_putc('1');
} else {
uart_putc('0');
}
if((received_char & (1<<0)) == (1<<0)) {
uart_putc('1');
} else {
uart_putc('0');
}
uart_puts("\n\r",2);
}
// function to initialize UART
// dataformat 8N1
void uart_init (void) {
// shift the register right by 8 bits
UBRRH = (BAUDRATE>>8);
// set baud rate
UBRRL = BAUDRATE;
// enable receiver, transmitter and receiver interrupt
UCSRB|= (1<<TXEN)|(1<<RXEN)|(1<<RXCIE);
// 8bit data format
UCSRC|= (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1);
}
// sends a single char over the UART
void uart_putc (unsigned char data) {
// wait while register is free
while (!( UCSRA & (1<<UDRE)));
// load data in the register
UDR = data;
}
// sends a string over the UART
void uart_puts (unsigned char * str, uint8_t size) {
uint8_t i;
for(i = 0; i < size; i++) {
uart_putc(str[i]);
}
}
// receives a single char over the UART
unsigned char uart_getc (void) {
// wait while data is being received
while(!(UCSRA) & (1<<RXC));
// return 8-bit data
return UDR;
}
uint8_t main (void) {
// enable interrupts
sei();
// enable uart
uart_init();
uart_puts("ready\n\r", 7);
while(1) {
}
return 0;
}
In GtkTerm I send the following byte sequence: 0x01, 0x02, 0x03, 0x1d, 0x1e, 0x1f, 0x20 and interrupt service routine ISR responds with the following sequence.
However, I should receive received=00100000 for 0x20
Whats wrong?

From my comment:
Maybe the baud rate is off due to using a slow clock rate / internal RC oszillator? The slower the baud rate, the greater the offset from the "middle" of each bit. This can lead to skipping bits or the controller seeing a bit twice.

Related

PN532 Trying to obtain Model number of device from Felica tags

I'm just an Arduino Uno to obtain the device number from Felica tags but the memory would just output 0xff. I'm also using I2C instead of SPI and I'm not sure if this matters.
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_PN532.h>
// If using the breakout with SPI, define the pins for SPI communication.
#define PN532_SCK (2)
#define PN532_MOSI (3)
#define PN532_SS (4)
#define PN532_MISO (5)
// If using the breakout or shield with I2C, define just the pins connected
// to the IRQ and reset lines. Use the values below (2, 3) for the shield!
#define PN532_IRQ (2)
#define PN532_RESET (3) // Not connected by default on the NFC Shield
// Uncomment just _one_ line below depending on how your breakout or shield
// is connected to the Arduino:
// Use this line for a breakout with a SPI connection:
//Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS);
// Use this line for a breakout with a hardware SPI connection. Note that
// the PN532 SCK, MOSI, and MISO pins need to be connected to the Arduino's
// hardware SPI SCK, MOSI, and MISO pins. On an Arduino Uno these are
// SCK = 13, MOSI = 11, MISO = 12. The SS line can be any digital IO pin.
//Adafruit_PN532 nfc(PN532_SS);
// Or use this line for a breakout or shield with an I2C connection:
Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET);
#if defined(ARDUINO_ARCH_SAMD)
// for Zero, output on USB Serial console, remove line below if using programming port to program the Zero!
// also change #define in Adafruit_PN532.cpp library file
#define Serial SerialUSB
#endif
uint8_t _prevIDm[8]; //IDm of the card previously detected
unsigned long _prevTime;
void setup(void) {
#ifndef ESP8266
while (!Serial); // for Leonardo/Micro/Zero
#endif
Serial.begin(115200);
Serial.println("Hello!");
nfc.begin();
uint32_t versiondata = nfc.getFirmwareVersion();
if (! versiondata) {
Serial.print("Didn't find PN53x board");
while (1); // halt
}
// Got ok data, print it out!
Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX);
Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC);
Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
// Set the max number of retry attempts to read from a card
// This prevents us from waiting forever for a card, which is
// the default behaviour of the PN532.
nfc.setPassiveActivationRetries(0xFF);
// configure board to read RFID tags
nfc.SAMConfig();
Serial.println("Waiting for an FeliCa card");
}
void loop(void) {
uint8_t ret;
uint16_t systemCode = 0xFFFF;
uint8_t requestCode = 0x01; // System Code request
uint8_t idm[8];
uint8_t pmm[8];
uint16_t systemCodeResponse;
// Wait for an FeliCa type cards.
// When one is found, some basic information such as IDm, PMm, and System Code are retrieved.
Serial.print("Waiting for an FeliCa card... ");
ret = nfc.felica_Polling(systemCode, requestCode, idm, pmm, &systemCodeResponse, 5000);
if (ret != 1)
{
Serial.println("Could not find a card");
delay(500);
return;
}
if ( memcmp(idm, _prevIDm, 8) == 0 ) {
if ( (millis() - _prevTime) < 3000 ) {
Serial.println("Same card");
delay(500);
return;
}
}
Serial.println("Found a card!");
Serial.print(" IDm: ");
nfc.PrintHex(idm, 8);
Serial.print(" PMm: ");
nfc.PrintHex(pmm, 8);
Serial.print(" System Code: ");
nfc.PrintHex16(systemCodeResponse);
Serial.print("\n");
memcpy(_prevIDm, idm, 8);
_prevTime = millis();
Serial.print("Request Service command -> ");
//Code to indicate System FFFFh
uint16_t nodeCodeList[3] = {0x0000, 0x1000, 0xFFFF};
uint16_t keyVersions[3];
ret = nfc.felica_RequestService(3, nodeCodeList, keyVersions);
if (ret != 1)
{
Serial.println("error");
} else {
Serial.println("OK!");
for(int i=0; i<3; i++ ) {
Serial.print(" Node Code: "); nfc.PrintHex16(nodeCodeList[i]);
Serial.print(" -> Key Version: "); nfc.PrintHex16(keyVersions[i]);
Serial.println("");
}
}
Serial.print("Read Without Encryption command -> ");
uint8_t blockData[3][16];
uint16_t serviceCodeList[1] = {0x000B};
uint16_t blockList[3] = {0x8000, 0x8001, 0x8002};
ret = nfc.felica_ReadWithoutEncryption(1, serviceCodeList, 3, blockList, blockData);
if (ret != 1)
{
Serial.println("error");
} else {
Serial.println("OK!");
for(int i=0; i<3; i++ ) {
Serial.print(" Block no. "); Serial.print(i, DEC); Serial.print(": ");
nfc.PrintHex(blockData[i], 16);
}
}
Serial.print("Request Response command -> ");
uint8_t mode;
ret = nfc.felica_RequestResponse(&mode);
if (ret != 1)
{
Serial.println("error");
} else {
Serial.println("OK!");
Serial.print(" mode: "); Serial.println(mode, DEC);
}
Serial.print("Request System Code command -> ");
uint8_t numSystemCode;
uint16_t systemCodeList[16];
ret = nfc.felica_RequestSystemCode(&numSystemCode, systemCodeList);
if (ret != 1)
{
Serial.println("error");
} else {
Serial.println("OK!");
for(int i=0; i< numSystemCode; i++) {
Serial.print(" System code: "); nfc.PrintHex16(systemCodeList[i]); Serial.println("");
}
}
// Wait 1 second before continuing
Serial.println("Card access completed!\n");
//delay(1000);
}
Here is my library .cpp
/***** FeliCa Functions ******/
/**************************************************************************/
/*!
#brief Poll FeliCa card. PN532 acting as reader/initiator,
peer acting as card/responder.
#param[in] systemCode Designation of System Code. When sending FFFFh as System Code,
all the FeliCa cards can return response.
#param[in] requestCode Designation of Request Data as follows:
00h: No Request
01h: System Code request (to acquire System Code of the card)
02h: Communication perfomance request
#param[out] idm IDm of the card (8 bytes)
#param[out] pmm PMm of the card (8 bytes)
#param[out] systemCodeResponse System Code of the card (2bytes)
#return 1: A FeliCa card has detected, 0: No card has detected, -1: error
*/
/**************************************************************************/
int8_t Adafruit_PN532::felica_Polling(uint16_t systemCode, uint8_t requestCode,
uint8_t *idm, uint8_t *pmm, uint16_t *systemCodeResponse, uint16_t timeout)
{
pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET;
pn532_packetbuffer[1] = 1;
pn532_packetbuffer[2] = 1;
pn532_packetbuffer[3] = FELICA_CMD_POLLING;
pn532_packetbuffer[4] = (systemCode >> 8) & 0xff;
pn532_packetbuffer[5] = systemCode & 0xFF;
pn532_packetbuffer[6] = requestCode;
pn532_packetbuffer[7] = 0;
if (!sendCommandCheckAck(pn532_packetbuffer,8,timeout)) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.println(F("Could not send Polling command"));
#endif
return -1;
}
// Wait card response
if (!waitready(timeout)) {
return -2;
}
readdata(pn532_packetbuffer, 9+20+2);
if ( !felica_checkResponse(PN532_RESPONSE_INLISTPASSIVETARGET) ) {
return -2;
}
// Check NbTg (pn532_packetbuffer[7])
if (pn532_packetbuffer[7] == 0) {
// No card have found
return 0;
} else if (pn532_packetbuffer[7] != 1) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.print (F("Unhandled number of targets inlisted. NbTg = "));
PN532DEBUGPRINT.println(pn532_packetbuffer[7], HEX);
#endif
return -3;
}
_inListedTag = pn532_packetbuffer[8];
#ifdef PN532DEBUG
PN532DEBUGPRINT.print(F("Tag number: "));
PN532DEBUGPRINT.println(_inListedTag);
#endif
// length check
uint8_t responseLength = pn532_packetbuffer[9];
if (responseLength != 18 && responseLength != 20) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.println(F("Wrong response length"));
#endif
return -4;
}
uint8_t i;
for (i=0; i<8; ++i) {
idm[i] = pn532_packetbuffer[11+i];
_felicaIDm[i] = pn532_packetbuffer[11+i];
pmm[i] = pn532_packetbuffer[19+i];
_felicaPMm[i] = pn532_packetbuffer[19+i];
}
if ( responseLength == 20 ) {
*systemCodeResponse = (uint16_t)((pn532_packetbuffer[26] << 8) + pn532_packetbuffer[27]);
}
return 1;
}
/**************************************************************************/
/*!
#brief Sends an FeliCa command with the currently inlisted peer
#param[in] commandBuf FeliCa command packet. (e.g. 00 FF FF 00 00 for Polling command)
#param[in] commandlength Length of the FeliCa command packet. (e.g. 0x05 for above Polling command )
#param[out] responseBuf FeliCa response packet. (e.g. 01 NFCID2(8 bytes) PAD for Polling response)
#param[out] responselength Length of the FeliCa response packet. (e.g. 0x12 for above Polling command )
*/
/**************************************************************************/
int8_t Adafruit_PN532::felica_SendCommand (const uint8_t *commandBuf, uint8_t commandlength,
uint8_t *responseBuf, uint8_t expectedResLen, uint8_t *responseLength)
{
if (commandlength > PN532_PACKBUFFSIZ-3) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.println(F("Command length too long for packet buffer"));
#endif
return -1;
}
pn532_packetbuffer[0] = 0x40; // PN532_COMMAND_INDATAEXCHANGE;
pn532_packetbuffer[1] = _inListedTag;
pn532_packetbuffer[2] = commandlength + 1;
memcpy(&pn532_packetbuffer[3], commandBuf, commandlength);
if (!sendCommandCheckAck(pn532_packetbuffer,commandlength+3,200)) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.println(F("Could not send Command"));
#endif
return -2;
}
// Wait card response ( longer than 102.4ms )
if (!waitready(110)) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.println(F("Could not receive response"));
#endif
return -3;
}
readdata(pn532_packetbuffer,expectedResLen);
if ( !felica_checkResponse(PN532_RESPONSE_INDATAEXCHANGE) ) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.println(F("Could not receive response"));
#endif
return -3;
}
// Check status (pn532_packetbuffer[7])
if ((pn532_packetbuffer[7] & 0x3F)!=0) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.print(F("Status code indicates an error: "));
PN532DEBUGPRINT.println(pn532_packetbuffer[7], HEX);
#endif
return -4;
}
// length check
*responseLength = pn532_packetbuffer[8] - 1;
if (pn532_packetbuffer[3] - 4 != *responseLength) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.println(F("Wrong response length"));
#endif
return -5;
}
memcpy(responseBuf, &pn532_packetbuffer[9], *responseLength);
return 1;
}
/**************************************************************************/
/*!
#brief Sends FeliCa Request Service command
#param[in] numNode Number of Node
#param[in] nodeCodeList Node Code List (Big Endian)
#param[out] keyVersions Key Version of each Node (Big Endian)
*/
/**************************************************************************/
int8_t Adafruit_PN532::felica_RequestService(uint8_t numNode, uint16_t *nodeCodeList, uint16_t *keyVersions)
{
if (numNode > FELICA_REQ_SERVICE_MAX_NODE_NUM) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.println(F("numNode is too large"));
#endif
return -1;
}
uint8_t i, j=0;
uint8_t cmdLen = 1 + 8 + 1 + 2*numNode;
uint8_t cmd[cmdLen];
cmd[j++] = FELICA_CMD_REQUEST_SERVICE;
for (i=0; i<8; ++i) {
cmd[j++] = _felicaIDm[i];
}
cmd[j++] = numNode;
for (i=0; i<numNode; ++i) {
cmd[j++] = nodeCodeList[i] & 0xFF;
cmd[j++] = (nodeCodeList[i] >> 8) & 0xff;
}
uint8_t responseBuf[10+2*numNode];
uint8_t responseLength;
if (!felica_SendCommand(cmd, cmdLen, responseBuf, 8 + 11 + 2*numNode + 2, &responseLength)) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.println(F("Request Service command failed"));
#endif
return -2;
}
// length check
if ( responseLength != 10+2*numNode ) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.println(F("Request Service command failed (wrong response length)"));
#endif
return -3;
}
for(i=0; i<numNode; i++) {
keyVersions[i] = (uint16_t)(responseBuf[10+i*2] + (responseBuf[10+i*2+1] << 8));
}
return 1;
}
/**************************************************************************/
/*!
#brief Sends FeliCa Request Service command
#param[out] mode Current Mode of the card
*/
/**************************************************************************/
int8_t Adafruit_PN532::felica_RequestResponse(uint8_t *mode)
{
uint8_t cmd[9];
cmd[0] = FELICA_CMD_REQUEST_RESPONSE;
memcpy(&cmd[1], _felicaIDm, 8);
uint8_t responseBuf[10];
uint8_t responseLength;
if (!felica_SendCommand(cmd, 9, responseBuf, 8 + 11 + 2, &responseLength)) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.println(F("Request Response command failed"));
#endif
return -1;
}
// length check
if ( responseLength != 10) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.println(F("Request Response command failed (wrong response length)"));
#endif
return -2;
}
*mode = responseBuf[9];
return 1;
}
/**************************************************************************/
/*!
#brief Sends FeliCa Read Without Encryption command
#param[in] numService Number of Service
#param[in] serviceCodeList Service Code List (Big Endian)
#param[in] numBlock Number of Block (This API only accepts 2-byte block list element)
#param[in] blockList Block List
#param[out] blockData Block Data
*/
/**************************************************************************/
int8_t Adafruit_PN532::felica_ReadWithoutEncryption (uint8_t numService, const uint16_t *serviceCodeList,
uint8_t numBlock, const uint16_t *blockList, uint8_t blockData[][16])
{
if (numService > FELICA_READ_MAX_SERVICE_NUM) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.println(F("numService is too large"));
#endif
return -1;
}
if (numBlock > FELICA_READ_MAX_BLOCK_NUM) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.println(F("numBlock is too large"));
#endif
return -2;
}
uint8_t i, j=0;
uint8_t cmdLen = 1 + 8 + 1 + 2*numService + 1 + 2*numBlock;
uint8_t cmd[cmdLen];
cmd[j++] = FELICA_CMD_READ_WITHOUT_ENCRYPTION;
for (i=0; i<8; ++i) {
cmd[j++] = _felicaIDm[i];
}
cmd[j++] = numService;
for (i=0; i<numService; ++i) {
cmd[j++] = serviceCodeList[i] & 0xFF;
cmd[j++] = (serviceCodeList[i] >> 8) & 0xff;
}
cmd[j++] = numBlock;
for (i=0; i<numBlock; ++i) {
cmd[j++] = (blockList[i] >> 8) & 0xFF;
cmd[j++] = blockList[i] & 0xff;
}
uint8_t responseBuf[12+16*numBlock];
uint8_t responseLength;
if (!felica_SendCommand(cmd, cmdLen, responseBuf, 8+13+16*numBlock + 2, &responseLength)) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.println(F("Read Without Encryption command failed"));
#endif
return -3;
}
// length check
if ( responseLength != 12+16*numBlock ) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.println(F("Read Without Encryption command failed (wrong response length)"));
#endif
return -4;
}
// status flag check
if ( responseBuf[9] != 0 || responseBuf[10] != 0 ) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.print(F("Read Without Encryption command failed (Status Flag: "));
PrintHex8(pn532_packetbuffer[9]);
PrintHex8(pn532_packetbuffer[10]);
PN532DEBUGPRINT.println(F(")"));
#endif
return -5;
}
int k = 12;
for(i=0; i<numBlock; i++ ) {
for(j=0; j<16; j++ ) {
blockData[i][j] = responseBuf[k++];
}
}
return 1;
}
/**************************************************************************/
/*!
#brief Sends FeliCa Write Without Encryption command
#param[in] numService Number of Service.
#param[in] serviceCodeList Service Code List.
#param[in] numBlock Number of Block. (This API only accepts 2-byte block list element)
#param[in] blockList Block List.
#param[out] blockData Block Data.
#return = 1: Success
< 0: error
*/
/**************************************************************************/
int8_t Adafruit_PN532::felica_WriteWithoutEncryption (uint8_t numService, const uint16_t *serviceCodeList,
uint8_t numBlock, const uint16_t *blockList, uint8_t blockData[][16])
{
if (numService > FELICA_WRITE_MAX_SERVICE_NUM) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.println(F("numService is too large"));
#endif
}
if (numBlock > FELICA_WRITE_MAX_BLOCK_NUM) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.println(F("numBlock is too large"));
#endif
return -2;
}
uint8_t i, j=0, k;
uint8_t cmdLen = 1 + 8 + 1 + 2*numService + 1 + 2*numBlock + 16 * numBlock;
uint8_t cmd[cmdLen];
cmd[j++] = FELICA_CMD_WRITE_WITHOUT_ENCRYPTION;
for (i=0; i<8; ++i) {
cmd[j++] = _felicaIDm[i];
}
cmd[j++] = numService;
for (i=0; i<numService; ++i) {
cmd[j++] = serviceCodeList[i] & 0xFF;
cmd[j++] = (serviceCodeList[i] >> 8) & 0xff;
}
cmd[j++] = numBlock;
for (i=0; i<numBlock; ++i) {
cmd[j++] = (blockList[i] >> 8) & 0xFF;
cmd[j++] = blockList[i] & 0xff;
}
for (i=0; i<numBlock; ++i) {
for(k=0; k<16; k++) {
cmd[j++] = blockData[i][k];
}
}
uint8_t response[11];
uint8_t responseLength;
if (felica_SendCommand(cmd, cmdLen, response, 8+12+2, &responseLength) != 1) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.println(F("Write Without Encryption command failed"));
#endif
return -3;
}
// length check
if ( responseLength != 11 ) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.println(F("Write Without Encryption command failed (wrong response length)"));
#endif
return -4;
}
// status flag check
if ( response[9] != 0 || response[10] != 0 ) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.print(F("Write Without Encryption command failed (Status Flag: "));
PrintHex8(pn532_packetbuffer[9]);
PrintHex8(pn532_packetbuffer[10]);
PN532DEBUGPRINT.println(F(")"));
#endif
return -5;
}
return 1;
}
/**************************************************************************/
/*!
#brief Sends FeliCa Request System Code command
#param[out] numSystemCode Number of System Code (1 byte)
#param[out] systemCodeList System Code list
*/
/**************************************************************************/
int8_t Adafruit_PN532::felica_RequestSystemCode(uint8_t *numSystemCode, uint16_t *systemCodeList)
{
uint8_t cmd[9];
cmd[0] = FELICA_CMD_REQUEST_SYSTEM_CODE;
memcpy(&cmd[1], _felicaIDm, 8);
uint8_t responseBuf[10 + 2 * 16];
uint8_t responseLength;
if (!felica_SendCommand(cmd, 9, responseBuf, 8+11+32+2, &responseLength)) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.println(F("Request System Code command failed"));
#endif
return -1;
}
*numSystemCode = responseBuf[9];
// length check
if ( responseLength < 10 + 2 * *numSystemCode ) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.println(F("Request System Code command failed (wrong response length)"));
#endif
return -2;
}
uint8_t i;
for(i=0; i<*numSystemCode; i++) {
systemCodeList[i] = (uint16_t)((responseBuf[10+i*2]<< 8) + responseBuf[10+i*2+1]);
}
return 1;
}
/**************************************************************************/
/*!
#brief Release FeliCa card
*/
/**************************************************************************/
int8_t Adafruit_PN532::felica_Release()
{
// InRelease
pn532_packetbuffer[0] = PN532_COMMAND_INRELEASE;
pn532_packetbuffer[1] = 0x00; // All target
#ifdef PN532DEBUG
PN532DEBUGPRINT.println(F("Release all FeliCa target"));
#endif
if (! sendCommandCheckAck(pn532_packetbuffer, 2))
return -1; // no ACK
readdata(pn532_packetbuffer,sizeof(pn532_packetbuffer));
if ( !felica_checkResponse(PN532_RESPONSE_INRELEASE) ) {
return -2;
}
if ((pn532_packetbuffer[7] & 0x3F)!=0) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.print(F("Status code indicates an error: "));
PN532DEBUGPRINT.println(pn532_packetbuffer[7], HEX);
#endif
return -3;
}
/*
// Power off RF
pn532_packetbuffer[0] = PN532_COMMAND_RFCONFIGURATION;
pn532_packetbuffer[1] = 1; // Config item 1 (RF field )
pn532_packetbuffer[2] = 0x00; // AutoRFCA is off, RF is off
#ifdef PN532DEBUG
PN532DEBUGPRINT.println(F("Turning RF off"));
#endif
if (! sendCommandCheckAck(pn532_packetbuffer, 3))
return false; // no ACK
// Wait more than 20 ms
delay(20);
// Power on RF
pn532_packetbuffer[0] = PN532_COMMAND_RFCONFIGURATION;
pn532_packetbuffer[1] = 1; // Config item 1 (RF field )
pn532_packetbuffer[2] = 0x01; // AutoRFCA is off, RF is off
#ifdef PN532DEBUG
PN532DEBUGPRINT.println(F("Turning RF on"));
#endif
if (! sendCommandCheckAck(pn532_packetbuffer, 3))
return false; // no ACK
*/
return 1;
}
bool Adafruit_PN532::felica_checkResponse(uint8_t PN532_command)
{
if (pn532_packetbuffer[0] != 0 || pn532_packetbuffer[1] != 0 || pn532_packetbuffer[2] != 0xff) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.println(F("Preamble missing"));
#endif
return false;
}
uint8_t length = pn532_packetbuffer[3];
if (pn532_packetbuffer[4]!=(uint8_t)(~length+1)) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.println(F("Length check invalid"));
PN532DEBUGPRINT.println(length,HEX);
PN532DEBUGPRINT.println((~length)+1,HEX);
#endif
return false;
}
if (pn532_packetbuffer[5]!=PN532_PN532TOHOST || pn532_packetbuffer[6]!=PN532_command) {
#ifdef PN532DEBUG
PN532DEBUGPRINT.print(F("Wrong TFI in response: "));
PN532DEBUGPRINT.println(pn532_packetbuffer[6],HEX);
#endif
return false;
}
return true;
}
/************** high level communication functions (handles both I2C and SPI) */
/**************************************************************************/
/*!
#brief Tries to read the SPI or I2C ACK signal
*/
/**************************************************************************/
bool Adafruit_PN532::readack() {
uint8_t ackbuff[6];
readdata(ackbuff, 6);
return (0 == strncmp((char *)ackbuff, (char *)pn532ack, 6));
}
/**************************************************************************/
/*!
#brief Return true if the PN532 is ready with a response.
*/
/**************************************************************************/
bool Adafruit_PN532::isready() {
if (_usingSPI) {
// SPI read status and check if ready.
#ifdef SPI_HAS_TRANSACTION
if (_hardwareSPI) SPI.beginTransaction(PN532_SPI_SETTING);
#endif
digitalWrite(_ss, LOW);
delay(2);
spi_write(PN532_SPI_STATREAD);
// read byte
uint8_t x = spi_read();
digitalWrite(_ss, HIGH);
#ifdef SPI_HAS_TRANSACTION
if (_hardwareSPI) SPI.endTransaction();
#endif
// Check if status is ready.
return x == PN532_SPI_READY;
}
else {
// I2C check if status is ready by IRQ line being pulled low.
uint8_t x = digitalRead(_irq);
return x == 0;
}
}
/**************************************************************************/
/*!
#brief Waits until the PN532 is ready.
#param timeout Timeout before giving up
*/
/**************************************************************************/
bool Adafruit_PN532::waitready(uint16_t timeout) {
uint16_t timer = 0;
while(!isready()) {
if (timeout != 0) {
timer += 10;
if (timer > timeout) {
PN532DEBUGPRINT.println("TIMEOUT!");
return false;
}
}
delay(10);
}
return true;
}
/**************************************************************************/
/*!
#brief Reads n bytes of data from the PN532 via SPI or I2C.
#param buff Pointer to the buffer where data will be written
#param n Number of bytes to be read
*/
/**************************************************************************/
void Adafruit_PN532::readdata(uint8_t* buff, uint8_t n) {
if (_usingSPI) {
// SPI write.
#ifdef SPI_HAS_TRANSACTION
if (_hardwareSPI) SPI.beginTransaction(PN532_SPI_SETTING);
#endif
digitalWrite(_ss, LOW);
delay(2);
spi_write(PN532_SPI_DATAREAD);
#ifdef PN532DEBUG
PN532DEBUGPRINT.print(F("Reading: "));
#endif
for (uint8_t i=0; i<n; i++) {
delay(1);
buff[i] = spi_read();
#ifdef PN532DEBUG
PN532DEBUGPRINT.print(F(" 0x"));
PN532DEBUGPRINT.print(buff[i], HEX);
#endif
}
#ifdef PN532DEBUG
PN532DEBUGPRINT.println();
#endif
digitalWrite(_ss, HIGH);
#ifdef SPI_HAS_TRANSACTION
if (_hardwareSPI) SPI.endTransaction();
#endif
}
else {
// I2C write.
uint16_t timer = 0;
delay(2);
#ifdef PN532DEBUG
PN532DEBUGPRINT.print(F("Reading: "));
#endif
// Start read (n+1 to take into account leading 0x01 with I2C)
WIRE.requestFrom((uint8_t)PN532_I2C_ADDRESS, (uint8_t)(n+2));
// Discard the leading 0x01
i2c_recv();
for (uint8_t i=0; i<n; i++) {
delay(1);
buff[i] = i2c_recv();
#ifdef PN532DEBUG
PN532DEBUGPRINT.print(F(" 0x"));
PN532DEBUGPRINT.print(buff[i], HEX);
#endif
}
// Discard trailing 0x00 0x00
// i2c_recv();
#ifdef PN532DEBUG
PN532DEBUGPRINT.println();
#endif
}
}
}
Here is my output
Waiting for an FeliCa card... Found a card!
IDm: 0x01 0x27 0x04 0x7E 0x49 0x5F 0x4E 0xB3
PMm: 0x00 0xF2 0x00 0x00 0x00 0x01 0x12 0x00
System Code: 0x0088
Request Service command -> error
Read Without Encryption command -> OK!
Block no. 0: 0x10 0x04 0x01 0x00 0x0D 0x00 0x00 0x00 0x00 0x00 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
Block no. 1: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
Block no. 2: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
Request Response command -> error
Request System Code command -> OK!
System code: 0x0B00
Card access completed!
My goal is to decode the memory and obtain the model numbers and if possible the MAC address so I can sync it up with Bluetooth with RPI.

Windows API to Arduino Serial write works once but sends corrupted data when the same message is rewritten

I am using a third party WinAPI-based Serial library (SerialPort) in a C++ program to command a LED strip (iLED and pixel color), but it turns out it only seems to work for one command - if I send the same command a second time, the color of that pixel takes another random colour and for some reason the first LED turns on too with a random colour.
Here is a link to a video of what happens when the simplified code below is run, i.e. when pixel 3, 5 and 7 are commanded over and over to be red, green, and blue respectively.
https://drive.google.com/file/d/1RRAshnhPz96YGJtmETy3vuGi25QjxqJz/view?usp=drivesdk
I suspected the Serial.read() weren't synchronised so I added a start byte but it didn't seem to work either, that's what the code below does.
What is happening ?
SerialPort.h (source: https://blog.manash.me/serial-communication-with-an-arduino-using-c-on-windows-d08710186498)
#ifndef SERIALPORT_H
#define SERIALPORT_H
#define ARDUINO_WAIT_TIME 2000
#define MAX_DATA_LENGTH 255
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
class SerialPort
{
private:
HANDLE handler;
bool connected;
COMSTAT status;
DWORD errors;
public:
SerialPort(char const *portName, unsigned long baudrate);
~SerialPort();
int readSerialPort(char *buffer, unsigned int buf_size);
bool writeSerialPort(char *buffer, unsigned int buf_size);
bool isConnected();
};
#endif // SERIALPORT_H
SerialPort.cpp (source: https://blog.manash.me/serial-communication-with-an-arduino-using-c-on-windows-d08710186498)
#include "serialport.h"
SerialPort::SerialPort(char const *portName, unsigned long baudrate)
{
this->connected = false;
this->handler = CreateFileA(static_cast<LPCSTR>(portName),
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (this->handler == INVALID_HANDLE_VALUE){
if (GetLastError() == ERROR_FILE_NOT_FOUND){
printf("ERROR: Handle was not attached. Reason: %s not available\n", portName);
}
else
{
printf("ERROR!!!");
}
}
else {
DCB dcbSerialParameters = {0};
if (!GetCommState(this->handler, &dcbSerialParameters)) {
printf("failed to get current serial parameters");
}
else {
dcbSerialParameters.BaudRate = baudrate;
dcbSerialParameters.ByteSize = 8;
dcbSerialParameters.StopBits = ONESTOPBIT;
dcbSerialParameters.Parity = NOPARITY;
dcbSerialParameters.fDtrControl = DTR_CONTROL_ENABLE;
if (!SetCommState(handler, &dcbSerialParameters))
{
printf("ALERT: could not set Serial port parameters\n");
}
else {
this->connected = true;
PurgeComm(this->handler, PURGE_RXCLEAR | PURGE_TXCLEAR);
Sleep(ARDUINO_WAIT_TIME);
}
}
}
}
SerialPort::~SerialPort()
{
if (this->connected){
this->connected = false;
CloseHandle(this->handler);
}
}
int SerialPort::readSerialPort(char *buffer, unsigned int buf_size)
{
DWORD bytesRead;
unsigned int toRead;
ClearCommError(this->handler, &this->errors, &this->status);
if (this->status.cbInQue > 0){
if (this->status.cbInQue > buf_size){
toRead = buf_size;
}
else toRead = this->status.cbInQue;
}
if (ReadFile(this->handler, buffer, toRead, &bytesRead, NULL)) return bytesRead;
return 0;
}
bool SerialPort::writeSerialPort(char *buffer, unsigned int buf_size)
{
DWORD bytesSend;
if (!WriteFile(this->handler, (void*) buffer, buf_size, &bytesSend, 0)){
ClearCommError(this->handler, &this->errors, &this->status);
return false;
}
else return true;
}
bool SerialPort::isConnected()
{
return this->connected;
}
main.cpp
#include <iostream>
#include "serialport.h"
using namespace std;
int main()
{
SerialPort serial("COM3", 115200);
while(1) {
unsigned char buffer[] = {255,3, 254, 0, 0};
serial.writeSerialPort((char*)buffer, 4);
unsigned char buffer2[] = {255,5, 0, 254, 0};
serial.writeSerialPort((char*)buffer2, 4);
unsigned char buffer3[] = {255,7, 0, 0, 254};
serial.writeSerialPort((char*)buffer3, 4);
}
return 0;
}
Arduino firmware
#include <FastLED.h>
#define BAUDRATE 115200
#define N_BYTES_MSG 4
#define N_LEDS 120
#define DATA_PIN 6
CRGB leds[N_LEDS] = {0};
void setup() {
FastLED.addLeds<WS2811, DATA_PIN, BRG>(leds, N_LEDS); //I don't know why the colours are BRG on this strip
FastLED.show();
Serial.begin(BAUDRATE);
}
void loop() {
//Check for a quadruplet of bytes (iLED R G B) led by start byte
if(Serial.available() >= N_BYTES_MSG+1 && Serial.read() == 255) {
//Read message
unsigned char buf[N_BYTES_MSG] = {0};
for(unsigned char i=0; i < N_BYTES_MSG; i++) {
buf[i] = Serial.read();
}
if(buf[0] < N_LEDS) { //Valid ID
leds[buf[0]] = CRGB(buf[1],buf[2],buf[3]); //Update LED state in internal representation
FastLED.show(); //Refresh LEDs based on internal representation
}
}
}
Note that the LED strip seems to work properly on its own, since I successfully tested moving at constant speed a single pixel.
The LED strip itself is the easiest debug route I have since I didn't manage to make readSerialPort() work yet and the COM port is hogged by the program so I can't get a handle on it (can we sniff that somehow?).
I test serial.writeSerialPort on Windows 10 desktop with Arduino Uno. It works for me.
The following is the code I used:
On windows:
#include <iostream>
#include "serialport.h"
using namespace std;
int main()
{
SerialPort serial("COM4", 115200);
while (1) {
unsigned char buffer[] = { 255,3, 254, 0, 0 };
serial.writeSerialPort((char*)buffer, 5);
unsigned char buffer2[] = { 255,5, 0, 254, 0 };
serial.writeSerialPort((char*)buffer2, 5);
unsigned char buffer3[] = { 255,7, 0, 0, 254 };
serial.writeSerialPort((char*)buffer3, 5);
}
return 0;
}
On Arduino:
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX
#define BAUDRATE 115200
#define N_BYTES_MSG 4
#define N_LEDS 120
#define DATA_PIN 6
void setup() {
Serial.begin(BAUDRATE);
mySerial.begin(BAUDRATE);
mySerial.println("Start reading.");
delay(5000);
}
void loop() {
//Check for a quadruplet of bytes (iLED R G B) led by start byte
if(Serial.available() >= N_BYTES_MSG+1 && Serial.read() == 255) {
//Read message
unsigned char buf[N_BYTES_MSG] = {0};
for(unsigned char i=0; i < N_BYTES_MSG; i++) {
buf[i] = Serial.read();
}
for(unsigned char i=0; i < N_BYTES_MSG; i++) {
mySerial.print(buf[i]);
mySerial.print(",");
}
mySerial.print("\r\n");
//Serial.write("Read complete!");
}
}
I print the received data on Arduino:
I notice that the printed data messed up when the Windows sends fast as you did in the while(1) without delay. So try adding a delay between two writes to see if it works.
Add also note the problem as #paddy pointed out.
I didn't manage to make readSerialPort() work yet
Set unsigned int toRead = buf_size; in SerialPort.cpp works for me. Use the following code to read:
unsigned char readBuffer[20] = {};
serial.readSerialPort((char*)readBuffer, 20);
printf((char*)readBuffer);
printf("\n");
Read from Arduino result:

Adafruit SHT31-D and Raspberry Pi2 -- Unable to read data from sensor

hopefully one of you out there can help me!
I am trying to use the Adafruit SHT31-D (an i2c device) board with my Pi2. I am going off of this datasheet to guide my coding efforts. I am using Wiring Pi (wiringpi.com) to facilitate things.
I am able to successfully open a connection to the device, and sending commands seems to work fine, but I am unable to read data back! Here is the little mini library I have put together. I am hoping that one of you might have some experience with this sort of thing and be able to help me see where I've gone wrong.
To rule out any possible issues with the sensor hardware, I have tested it with my Arduino UNO and it works without issues.
Here is my C++ code:
SHT3x.h
#pragma once
/* Sensor Commands */
#define DEFAULT_SHT_ADDR 0x44
#define MEAS_HREP_STRETCH 0x2C06
#define MEAS_MREP_STRETCH 0x2C0D
#define MEAS_LREP_STRETCH 0x2C10
#define MEAS_HREP 0x2400
#define MEAS_MREP 0x240B
#define MEAS_LREP 0x2416
#include <cstdint>
class SHT3x {
public:
SHT3x(const uint8_t& i2cAddr);
float readHumidity(const uint16_t& command) const;
float readTempC(const uint16_t& command) const;
float readTempF(const uint16_t& command) const;
private:
int8_t _fd;
uint8_t _header;
uint32_t getMeasurement(const uint16_t& command) const;
void sendCommand(const uint16_t& command) const;
uint32_t receiveData(void) const;
};
SHT3x.cpp
#include <stdexcept>
#include <wiringPi.h>
#include <wiringPiI2C.h>
#include "SHT3x.h"
SHT3x::SHT3x(const uint8_t& i2cAddr) {
_fd = wiringPiI2CSetup(i2cAddr);
_header = i2cAddr << 1;
if (_fd < 0) {
throw std::runtime_error("Unable to connect");
}
}
float SHT3x::readHumidity(const uint16_t& command) const {
uint32_t raw_data = getMeasurement(command);
if (!raw_data) {
throw std::runtime_error("Bad Reading.");
}
uint16_t raw_humidity = raw_data & 0xFFFF;
float humidity = 100.0 * ((float) raw_humidity / (float) 0xFFFF);
return humidity;
}
float SHT3x::readTempC(const uint16_t& command) const {
uint32_t raw_data = getMeasurement(command);
if (!raw_data) {
throw std::runtime_error("Bad Reading.");
}
uint16_t raw_temp = raw_data >> 16;
float tempC = -45.0 + (175.0 * ((float) raw_temp / (float) 0xFFFF));
return tempC;
}
float SHT3x::readTempF(const uint16_t& command) const {
uint32_t raw_data = getMeasurement(command);
if (!raw_data) {
throw std::runtime_error("Bad Reading.");
}
uint16_t raw_temp = raw_data >> 16;
float tempF = -49.0 + (315.0 * ((float) raw_temp / (float) 0xFFFF));
return tempF;
}
uint32_t SHT3x::getMeasurement(const uint16_t& command) const {
try {
sendCommand(command);
} catch (std::runtime_error& e) {
throw;
}
return receiveData();
}
void SHT3x::sendCommand(const uint16_t& command) const {
// break command into bytes
uint8_t MSB = command >> 8;
uint8_t LSB = command & 0xFF;
// send header
int8_t ack = wiringPiI2CWrite(_fd, _header);
// send command
ack &= wiringPiI2CWrite(_fd, MSB);
ack &= wiringPiI2CWrite(_fd, LSB);
// handle errors
if (ack) {
throw std::runtime_error("Sending command failed.");
}
}
uint32_t SHT3x::receiveData(void) const {
uint32_t data;
// send header
uint8_t read_header = _header | 0x01;
int8_t ack = wiringPiI2CWrite(_fd, read_header);
// handle errors
if (ack) throw std::runtime_error("Unable to read data.");
// read data
data = wiringPiI2CRead(_fd);
for (size_t i = 0; i < 4; i++) {
printf("Data: %d\n", data);
data <<= 8;
if (i != 1) {
data |= wiringPiI2CRead(_fd);
} else {
wiringPiI2CRead(_fd); // skip checksum
}
}
wiringPiI2CRead(_fd); // second checksum
return data;
}
The SHT31 uses 16bit read and write, rather than using 2 8bit writes you might be better off using wiringpi's 16bit write. wiringPiI2CWriteReg16(). Same thing applies to the read.
Below is a very early copy of what I've done to read the sht31-d on a PI. It has no dependencies except i2c-dev. Heater enable/disable is not working, but softreset, clearstatus, getserial & get temp/humid are all fine.
/*
* Referances
* https://www.kernel.org/doc/Documentation/i2c/dev-interface
* https://github.com/adafruit/Adafruit_SHT31
* https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/Humidity_and_Temperature_Sensors/Sensirion_Humidity_and_Temperature_Sensors_SHT3x_Datasheet_digital.pdf
*
* This depends on i2c dev lib
* sudo apt-get install libi2c-dev
*
* Below is also a good one to have, but be careful i2cdump from the below cause the sht31 interface to become unstable for me
* and requires a hard-reset to recover correctly.
* sudo apt-get install i2c-tools
*
* on PI make sure below 2 commands are in /boot/config.txt
* dtparam=i2c_arm=on
* dtparam=i2c1_baudrate=10000
* I know we are slowing down the baurate from optimal, but it seems to be the most stable setting in my testing.
* add another 0 to the above baudrate for max setting, ie dtparam=i2c1_baudrate=100000
*/
#include <linux/i2c-dev.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <elf.h>
#include <unistd.h>
#define SHT31_INTERFACE_ADDR 1
#define SHT31_DEFAULT_ADDR 0x44
#define SHT31_READ_SERIALNO 0x3780
#define SHT31_MEAS_HIGHREP_STRETCH 0x2C06 // Doesn't work on PI
#define SHT31_MEAS_MEDREP_STRETCH 0x2C0D // Seems to work on PI but shouldn't
#define SHT31_MEAS_LOWREP_STRETCH 0x2C10 // Seems to work on PI but shouldn't
#define SHT31_MEAS_HIGHREP 0x2400 // Doesn't work on PI
#define SHT31_MEAS_MEDREP 0x240B
#define SHT31_MEAS_LOWREP 0x2416
#define SHT31_READSTATUS 0xF32D
#define SHT31_CLEARSTATUS 0x3041
#define SHT31_SOFTRESET 0x30A2
#define SHT31_HEATER_ENABLE 0x306D
#define SHT31_HEATER_DISABLE 0x3066
#define CHECK_BIT(var,pos) (((var)>>(pos)) & 1)
/*
* delay:
* Wait for some number of milliseconds
*********************************************************************************
*/
void delay (unsigned int howLong)
{
struct timespec sleeper, dummy ;
sleeper.tv_sec = (time_t)(howLong / 1000) ;
sleeper.tv_nsec = (long)(howLong % 1000) * 1000000 ;
nanosleep (&sleeper, &dummy) ;
}
/*
*
* CRC-8 formula from page 14 of SHT spec pdf
*
* Test data 0xBE, 0xEF should yield 0x92
*
* Initialization data 0xFF
* Polynomial 0x31 (x8 + x5 +x4 +1)
* Final XOR 0x00
*/
uint8_t crc8(const uint8_t *data, int len)
{
const uint8_t POLYNOMIAL = 0x31;
uint8_t crc = 0xFF;
int j;
int i;
for (j = len; j; --j ) {
crc ^= *data++;
for ( i = 8; i; --i ) {
crc = ( crc & 0x80 )
? (crc << 1) ^ POLYNOMIAL
: (crc << 1);
}
}
return crc;
}
/*
*
* buffer should return with data read, size defined by readsize
*********************************************************************************
*/
int writeandread(int fd, uint16_t sndword, uint8_t *buffer, int readsize)
{
int rtn;
uint8_t snd[3];
// Split the 16bit word into two 8 bits that are flipped.
snd[0]=(sndword >> 8) & 0xff;
snd[1]=sndword & 0xff;
rtn = write(fd, snd, 2);
if ( rtn != 2 ) {
return 1;
}
if (readsize > 0) {
delay(10);
rtn = read(fd, buffer, readsize);
if ( rtn < readsize) {
return 2;
}
}
return 0;
}
void printserialnum(int file)
{
uint8_t buf[10];
int rtn;
rtn = writeandread(file, SHT31_READ_SERIALNO, buf, 6);
if (rtn != 0)
printf("ERROR:- Get serial i2c %s failed\n",(rtn==1?"write":"read"));
else {
if (buf[2] != crc8(buf, 2) || buf[5] != crc8(buf+3, 2))
printf("WARNING:- Get serial CRC check failed, don't trust result\n");
uint32_t serialNo = ((uint32_t)buf[0] << 24)
| ((uint32_t)buf[1] << 16)
| ((uint32_t)buf[3] << 8)
| (uint32_t)buf[4];
printf("Serial# = %d\n",serialNo);
}
}
void printtempandhumidity(int file)
{
uint8_t buf[10];
int rtn;
rtn = writeandread(file, SHT31_MEAS_MEDREP_STRETCH, buf, 6);
if (rtn != 0)
printf("ERROR:- Get temp/humidity i2c %s failed\n",(rtn==1?"write":"read"));
else {
if ( buf[2] != crc8(buf, 2) || buf[5] != crc8(buf+3, 2))
printf("WARNING:- Get temp/humidity CRC check failed, don't trust results\n");
uint16_t ST, SRH;
ST = buf[0];
ST <<= 8;
ST |= buf[1];
SRH = buf[3];
SRH <<= 8;
SRH |= buf[4];
double stemp = ST;
stemp *= 175;
stemp /= 0xffff;
stemp = -45 + stemp;
double stempf = ST;
stempf *= 315;
stempf /= 0xffff;
stempf = -49 + stempf;
printf("Temperature %.2fc - %.2ff\n",stemp,stempf);
double shum = SRH;
shum *= 100;
shum /= 0xFFFF;
printf("Humidity %.2f%%\n",shum);
}
}
void printBitStatus(uint16_t stat)
{
printf("Status\n");
printf(" Checksum status %d\n", CHECK_BIT(stat,0));
printf(" Last command status %d\n", CHECK_BIT(stat,1));
printf(" Reset detected status %d\n", CHECK_BIT(stat,4));
printf(" 'T' tracking alert %d\n", CHECK_BIT(stat,10));
printf(" 'RH' tracking alert %d\n", CHECK_BIT(stat,11));
printf(" Heater status %d\n", CHECK_BIT(stat,13));
printf(" Alert pending status %d\n", CHECK_BIT(stat,15));
}
void printstatus(int file)
{
uint8_t buf[10];
int rtn;
rtn = writeandread(file, SHT31_READSTATUS, buf, 3);
if (rtn != 0)
printf("ERROR:- readstatus %s failed\n",(rtn==1?"write":"read"));
else {
if ( buf[2] != crc8(buf, 2))
printf("WARNING:- Get status CRC check failed, don't trust results\n");
uint16_t stat = buf[0];
stat <<= 8;
stat |= buf[1];
printBitStatus(stat);
}
}
void clearstatus(int file)
{
if( writeandread(file, SHT31_CLEARSTATUS, NULL, 0) != 0)
printf("ERROR:- sht31 clear status failed\n");
else
printf("Clearing status - ok\n");
}
void softreset(int file)
{
if( writeandread(file, SHT31_SOFTRESET, NULL, 0) != 0)
printf("ERROR:- sht31 soft reset failed\n");
else
printf("Soft reset - ok\n");
}
void enableheater(int file)
{
if( writeandread(file, SHT31_HEATER_ENABLE, NULL, 0) != 0)
printf("ERROR:- sht31 heater enable failed\n");
else
printf("Enabiling heater - ok\n");
}
void disableheater(int file)
{
if( writeandread(file, SHT31_HEATER_DISABLE, NULL, 0) != 0)
printf("ERROR:- sht31 heater enable failed\n");
else
printf("Disableing heater - ok\n");
}
int main()
{
int file;
char filename[20];
snprintf(filename, 19, "/dev/i2c-%d", SHT31_INTERFACE_ADDR);
file = open(filename, O_RDWR);
if (file < 0) {
printf("ERROR:- Can't open %s\n",filename);
exit(1);
}
if (ioctl(file, I2C_SLAVE, SHT31_DEFAULT_ADDR) < 0) {
printf("ERROR:- Connecting to sht31 I2C address 0x%02hhx\n", SHT31_DEFAULT_ADDR);
exit(1);
}
softreset(file);
printtempandhumidity(file);
printstatus(file);
close(file);
return 0;
}

error: expected unqualified-id before '{' token in Arduino

I'm having trouble with compiling my code for two I2C sensors. I keep getting the error: expected unqualified-id before '{' token.
Below is the code I am trying to solve:
#include <i2cmaster.h>
#include "Wire.h" // imports the wire library for talking over I2C
int led = 13;
//before void setup
#define SENSOR_ADDR_OFF_OFF (0x4B)
#define SENSOR_ADDR_OFF_ON (0x4A)
#define SENSOR_ADDR_ON_OFF (0x49)
#define SENSOR_ADDR_ON_ON (0x4m8)
// Set the sensor address here
const uint8_t sensorAddr = SENSOR_ADDR_OFF_OFF;
//void setup begins here
void setup()
{
// Start the serial port for output
Serial.begin(9600);
pinMode(led, OUTPUT);
// Join the I2C bus as master
Wire.begin();
// Set up the ADC on the sensor (reset everything)
i2c_init(); //Initialise the i2c bus
PORTC = (1 << PORTC4) | (1 << PORTC5);//enable pullups
}
//void loop begins here
void loop(){
int dev = 0x5A<<1;
int data_low = 0;
int data_high = 0;
int pec = 0;
i2c_start_wait(dev+I2C_WRITE);
i2c_write(0x07);
// read
i2c_rep_start(dev+I2C_READ);
data_low = i2c_readAck(); //Read 1 byte and then send ack
data_high = i2c_readAck(); //Read 1 byte and then send ack
pec = i2c_readNak();
i2c_stop();
//This converts high and low bytes together and processes temperature, MSB is a error bit and is ignored for temps
double tempFactor = 0.02; // 0.02 degrees per LSB (measurement resolution of the MLX90614)
double tempData = 0x0000; // zero out the data
int frac; // data past the decimal point
// This masks off the error bit of the high byte, then moves it left 8 bits and adds the low byte.
tempData = (double)(((data_high & 0x007F) << 8) + data_low);
tempData = (tempData * tempFactor)-0.01;
float celcius = tempData - 273.15;
float fahrenheit = (celcius*1.8) + 32;
Serial.print("Celcius: ");
Serial.println(celcius);
Serial.print("Fahrenheit: ");
Serial.println(fahrenheit);
}
uint8_t left;
uint8_t right;
{
if ((ReadByte(sensorAddr, 0x0, &left) == 0) &&
(ReadByte(sensorAddr, 0x1, &right) == 0))
{
// Use a threshold (value from 0-255) to determine if sensor detected a dark
// or light surface; the threshold should be modified according to the
// environment on which the sensor will be used
{
Serial.print("Left: ");
Serial.println(left);
}{
Serial.print("Right: ");
Serial.println(right);
}}
delay(1000);
}
// Read a byte on the i2c interface
int ReadByte(uint8_t addr, uint8_t reg, uint8_t *data)
{
// Do an i2c write to set the register that we want to read from
Wire.beginTransmission(addr);
Wire.write(reg);
Wire.endTransmission();
//Read a byte from the device
Wire.requestFrom(addr, (uint8_t)1);
if (Wire.available())
{
*data = Wire.read();
}
else
{
// Read nothing back
return -1;
}
return 0;
}
// Write a byte on the i2c interface
void WriteByte(uint8_t addr, uint8_t reg, byte data)
}
{
// Begin the write sequence
Wire.beginTransmission(addr);
// First byte is to set the register pointer
Wire.write(reg);
// Write the data byte
Wire.write(data);
// End the write sequence; bytes are actually transmitted now
Wire.endTransmission();
}
}
You have this function, which starts with the wrong brace type.
void WriteByte(uint8_t addr, uint8_t reg, byte data)
} // Remove this, it's wrong
{ // Opening brace
... the rest of your code ...
} // Closing brace
} // Another closing brace, but I don't know why (I'd just remove it too)
You should have.
void WriteByte(uint8_t addr, uint8_t reg, byte data)
{ // Opening brace
... the rest of your code ...
} // Closing brace

Asynchronous data reading from a barcode scanner over RS232 serial port

I have a bar-code reader which is connected to PC on RS232 serial port. I am writing a C++ code to send command to barcode scanner and get the response back to the PC. Currently program can send data to the device correctly but it is failed to read the response from barcode scanner. In this case once we send a command to barcode reader it will response back with a positive or negative acknowledgement.
e.g:- Send BEEP command.
1. Host(PC) send a BEEP command to barcode scanner
2. Barcode scanner make a beep sound and send the acknowledgement back
to host (PC)
3. Host (PC) read the acknowledgement
in below code first 2 step are working properly but I couldn't write third one correctly. Please somebody help me to correct my source code to read the response from barcode scanner asynchronously.
main.cpp
#include <iostream>
extern "C"
{
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
}
#include "DeviceRS232.h"
#include "Message.h"
int main()
{
unsigned char recvBuffer[257];
unsigned char ledOn[] = {0x05, 0xE7, 0x04, 0x00, 0x0D, 0x00};
unsigned char SSIBuffer[] = {0x00, 0xC6, 0x04, 0x08, 0x11, 0xEE, 0x01};
unsigned char requestRevision[] = {0x00, 0x04, 0xA3, 0x04, 0x00};
unsigned char sendBeep[] = {0x00, 0xE6, 0x04, 0x00, 0x05};
Message beepCommand(sendBeep, sizeof(sendBeep)/sizeof(sendBeep[0]));
std::cout << "*********************************************************" << std::endl << std::endl;
DeviceRS232 dev_rs232;
dev_rs232.setDefaultAttributes();
dev_rs232.openSerialPort();
// Send BEEP command several times.
std::cout << "---Start sending beep---" << std::endl;
for(int x=0; x<1; x++)
{
int sizeSent = dev_rs232.sendDataBuffer(beepCommand.getCommandData(), beepCommand.getLen());
if( sizeSent > 0)
{
std::cout << "Data sent: " << sizeSent << std::endl;
}
memset(recvBuffer, 0, sizeof(recvBuffer));
int recvSize = dev_rs232.receiveDataBuffer(recvBuffer, sizeof(recvBuffer));
std::cout << "Date Received, Data: " << recvBuffer << " Size: " << recvSize << std::endl;
sleep(2);
/**
while(true)
{
memset(recvBuffer, 0, sizeof(recvBuffer));
int recvSize = dev_rs232.receiveDataBuffer(recvBuffer, sizeof(recvBuffer));
if(recvSize > 0)
std::cout << "Date Received, Data: " << recvBuffer << " Size: " << recvSize << std::endl;
sleep(2);
}*/
}
std::cout << "---End sending beep-----\n" << std::endl;
dev_rs232.closeSerialPort();
std::cout << "*********************************************************" << std::endl;
return 0;
}
Message.h
#ifndef MESSAGE_H
#define MESSAGE_H
#include <iostream>
#include <string>
#include <numeric>
extern "C"
{
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
}
class Message
{
public:
Message(); // default constructor
virtual ~Message(); // destructor
Message(const std::basic_string<unsigned char> msg) : commandMsg(msg)
{
printf("msg[0]:%x\n", msg[4]);
std::cout << "length: " << commandMsg.length() << std::endl;
//commandMsg[0] = commandMsg.length();
appendChecksum();
};
Message(const unsigned char *msg, int msglen) : commandMsg(msg, msglen)
{
commandMsg[0] = commandMsg.length();
appendChecksum();
};
const unsigned char *getCommandData() const
{
return commandMsg.c_str();
}
int getLen() const
{
return commandMsg.length();
}
protected:
private:
int appendChecksum();
std::basic_string<unsigned char> commandMsg;
};
#endif // MESSAGE_H
Message.cpp
#include "Message.h"
Message::Message()
{
//ctor
}
Message::~Message()
{
//dtor
}
int Message::appendChecksum()
{
int sum = -std::accumulate(commandMsg.begin(), commandMsg.end(), 0);
commandMsg.push_back(0xFF & (sum >> 8));
commandMsg.push_back(0xFF & sum);
}
DeviceRS232.h
#ifndef DEVICERS232_H
#define DEVICERS232_H
extern "C"
{
#include <stdio.h>
#include <string.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <stdlib.h>
}
#include <string>
#define MAX_SERIAL_PORT_NO 30
class DeviceRS232
{
public:
DeviceRS232();
virtual ~DeviceRS232();
int fdRS232; // file descriptor for the serial port
void setSerialPort(std::string sp);
void setBaudRate(long baud);
void setDataBits(int dataBit);
void setStopBits(int stopBit);
void setNumberOfParityBits(int nparityBits);
void setDefaultAttributes();
long getBaudRate();
std::string getSerialPort();
int openSerialPort();
int readUserConfiguration();
int sendDataBuffer(const unsigned char *dataBuffer, size_t bufferSize);
int receiveDataBuffer(unsigned char *dataBuffer, size_t bufferSize);
void closeSerialPort();
protected:
std::string serialPort; // Serial port like /dev/ttyS0
long baudRate; // Scanner baud rate
int dataBits; // data bits
int stopBits; // stop bits
int numberOfParityBits; // number of parity bits
termios oldSerialPortSetting; // Current values of termios structure for /dev/ttyS0
termios newSerialPortSetting; // new termios attributes for /dev/ttyS0
private:
};
#endif // DEVICERS232_H
DeviceRS232.cpp
#include "DeviceRS232.h"
DeviceRS232::DeviceRS232()
{
//ctor
}
DeviceRS232::~DeviceRS232()
{
//dtor
}
void DeviceRS232::setSerialPort(std::string sp)
{
serialPort = sp;
}
void DeviceRS232::setBaudRate(long baud)
{
baudRate = baud;
}
void DeviceRS232::setDataBits(int dataBit)
{
dataBits = dataBit;
}
void DeviceRS232::setStopBits(int stopBit)
{
stopBits = stopBit;
}
void DeviceRS232::setNumberOfParityBits(int nparityBits)
{
numberOfParityBits = nparityBits;
}
void DeviceRS232::setDefaultAttributes()
{
std::string sp = "/dev/ttyS0";
long baud = 9600;
int dataBit = 1;
int stopBit = 1;
int nparityBits = 0;
setSerialPort(sp);
setBaudRate(baud);
setDataBits(dataBit);
setStopBits(stopBit);
setNumberOfParityBits(nparityBits);
}
long DeviceRS232::getBaudRate()
{
return baudRate;
}
std::string DeviceRS232::getSerialPort()
{
return serialPort;
}
int DeviceRS232::openSerialPort()
{
int fd, baudr, status, portStatus;
setDefaultAttributes();
switch(getBaudRate())
{
case 50 : baudr = B50;
break;
case 75 : baudr = B75;
break;
case 110 : baudr = B110;
break;
case 134 : baudr = B134;
break;
case 150 : baudr = B150;
break;
case 200 : baudr = B200;
break;
case 300 : baudr = B300;
break;
case 600 : baudr = B600;
break;
case 1200 : baudr = B1200;
break;
case 1800 : baudr = B1800;
break;
case 2400 : baudr = B2400;
break;
case 4800 : baudr = B4800;
break;
case 9600 : baudr = B9600;
break;
case 19200 : baudr = B19200;
break;
case 38400 : baudr = B38400;
break;
case 57600 : baudr = B57600;
break;
case 115200 : baudr = B115200;
break;
case 230400 : baudr = B230400;
break;
case 460800 : baudr = B460800;
break;
case 500000 : baudr = B500000;
break;
case 576000 : baudr = B576000;
break;
case 921600 : baudr = B921600;
break;
case 1000000 : baudr = B1000000;
break;
default : printf("invalid baudrate\n");
return(1);
break;
}
// Open serial port
fd = open(getSerialPort().c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
if(fd == -1)
{
printf("Unable to open serial port...\n");
perror(getSerialPort().c_str());
return 1;
}
fdRS232 = fd;
fcntl(fdRS232, F_SETFL, FNDELAY);
status = tcgetattr(fdRS232, &oldSerialPortSetting);
if(status == -1)
{
close(fdRS232);
printf("Unable to get serial port attributes...\n");
return 1;
}
memset(&newSerialPortSetting, 0, sizeof(newSerialPortSetting));
newSerialPortSetting.c_cflag = baudr | CS8 | CLOCAL | CREAD; //
newSerialPortSetting.c_iflag = IGNPAR;
newSerialPortSetting.c_oflag = 0;
newSerialPortSetting.c_lflag = 0;
newSerialPortSetting.c_cc[VMIN] = 0;
newSerialPortSetting.c_cc[VTIME] = 0;
status = tcsetattr(fdRS232, TCSANOW, &newSerialPortSetting);
if(status==-1)
{
close(fdRS232);
perror("unable to adjust portsettings ");
return 1;
}
// Get the status of opened serial port
if(ioctl(fdRS232, TIOCMGET, &portStatus) == -1)
{
perror("Unable to get port status");
return 1;
}
// Tern on DTR and RTS
portStatus |= TIOCM_DTR;
portStatus |= TIOCM_RTS;
// Set the status of the port with new DTR, RTS values
if(ioctl(fdRS232, TIOCMSET, &portStatus) == -1)
{
perror("Unable to set port status...");
return 1;
}
return 0;
}
int DeviceRS232::sendDataBuffer(const unsigned char *dataBuffer, size_t bufferSize)
{
return write(fdRS232, dataBuffer, bufferSize);
}
int DeviceRS232::receiveDataBuffer(unsigned char *dataBuffer, size_t bufferSize)
{
/**int recvSize = 0;
recvSize = read(fdRS232, dataBuffer, bufferSize);
return recvSize;*/
unsigned char recvBuffer[255];
unsigned char *ptrChar;
int nBytes;
ptrChar = recvBuffer;
memset(recvBuffer, 0x00, sizeof(recvBuffer));
while((nBytes = read(fdRS232, ptrChar, recvBuffer+sizeof(recvBuffer) - ptrChar -1)) > 0)
{
ptrChar += nBytes;
//printf("while - %d\n", nBytes);
}
//printf("recvBuffer : %x\n", recvBuffer[0]);
//printf("recvBuffer : %x\n", recvBuffer[1]);
//printf("recvBuffer : %x\n", recvBuffer[2]);
//printf("recvBuffer : %x\n", recvBuffer[3]);
//printf("recvBuffer : %x\n", recvBuffer[4]);
dataBuffer = recvBuffer;
return nBytes;
}
void DeviceRS232::closeSerialPort()
{
int portStatus;
if(ioctl(fdRS232, TIOCMGET, &portStatus) == -1)
{
perror("Unable to get the port status");
}
// Tern off DTR and RTS
portStatus &= ~TIOCM_DTR;
portStatus &= ~TIOCM_RTS;
// Set the status of the port with new DTR, RTS values
if(ioctl(fdRS232, TIOCMSET, &portStatus) == -1)
{
perror("Unable to set port status...");
}
close(fdRS232);
}
my bad method is int DeviceRS232::receiveDataBuffer(unsigned char *dataBuffer, size_t bufferSize)
Below is the console output:
*********************************************************
---Start sending beep---
Data sent: 7
Date Received, Data: Size: 0
---End sending beep-----
*********************************************************
Process returned 0 (0x0) execution time : 2.004 s
Press ENTER to continue.
As others have noted, one suspect area is the number of bytes you're sending. Instead of always sending 257 bytes, the barcode reader is probably expecting just the number of bytes in the command and no more.
Also, your code has a number of repeated operations for calculating the checksum at the end of the message. That suggests a class would help streamline the design. Here, then, is a Message class for that purpose:
#include <vector>
#include <numeric>
#include <string>
class Message
{
public:
Message(const std::basic_string<unsigned char> msg) : mymsg(msg) {
mymsg[0] = mymsg.length(); appendChecksum(); };
Message(const unsigned char *msg, int msglen) : mymsg(msg, msglen) {
mymsg[0] = mymsg.length(); appendChecksum(); };
const unsigned char *getData() const { return mymsg.c_str(); }
size_t getLen() const { return mymsg.length(); }
private:
int appendChecksum();
std::basic_string<unsigned char> mymsg;
};
int Message::appendChecksum()
{
int sum = -std::accumulate(mymsg.begin(), mymsg.end(), 0);
mymsg.push_back(0xff & (sum >> 8));
mymsg.push_back(0xff & sum);
return sum;
}
Now within your main routine, you can eliminate several dozen lines of code and use these instead (if you're using C++11):
Message setparams{{0x00, 0xc6, 0x04, 0x08, 0x11, 0xee, 0x01}};
Message beep{{0x00, 0xe6, 0x04, 0x00, 0x05}};
Message getrevision{{0x00, 0xA3, 0x04, 0x00}};
Message ledOn{{0x00, 0xe7, 0x04, 0x00, 0x0d, 0x00}};
If you're not using C++11 (which would be a shame!) you can use this slightly less clean style instead:
unsigned char parms[] = {0x00, 0xc6, 0x04, 0x08, 0x11, 0xee, 0x01};
Message setparams(parms,sizeof(parms)/sizeof(parms[0]));
Note that the first byte is set to zero instead of the length. This is done because the constructor automatically calculates and sets the proper length in that byte just before it calculates and appends the checksum. There are other ways to do this, of course, but I'll leave that to you.
Finally, with your loop, you can now use this line:
int sizeSent = dev_rs232.sendDataBuffer(beep.getData(), beep.getLen());
That may or may not actually solve the problem, but it will assist you to have a cleaner program to start with.
Also, a few pieces of style and design advice:
get out of the habit of using namespace std
use iostream instead of printf
instead of having to call setDefaultAttributes() immediately after creating the device, have the constructor set up sane defaults
eliminate "magic numbers" such as 4096 for the receive buffer size. Instead, use named static const. It will make the program more understandable and maintainable.
consider using an existing library such as boost::asio instead of rolling your own
Good luck!
Edit: Based on your keen (and correct!) observation that the Message constructor doesn't work properly when fed a plain unsigned char *, I've added a second constructor and modified the non C++11 version of the code. Sorry for any inconvenience, and thanks for keeping me honest.
/**
* Receive responses from the decoder
*/
int DeviceRS232::receiveDecodedData(unsigned char *dataBuffer, size_t bufferSize)
{
unsigned char recvBuffer[251];
unsigned char *ptrChar;
int nBytes, portStatus;
int inputBufSize = 0;
ChangeCTS(fdRS232, 0);
ChangeRTS(fdRS232, 0);
while(inputBufSize <= 0)
{
ioctl(fdRS232, FIONREAD, &inputBufSize);
usleep(1);
}
if(inputBufSize > 0)
{
int decodePacketLen = 0;
//unsigned char
memset(recvBuffer, 0x00, sizeof(recvBuffer));
nBytes = 0;
//usleep(100000);
while(nBytes < ((int)recvBuffer[0] + 2))
{
int index = 0;
int recvDataLen = 0;
if(nBytes != 0)
index = nBytes - 1;
recvDataLen = read(fdRS232, &recvBuffer[index], 251);
if(recvDataLen < 0)
{
std::cout << "[INFO#DeviceRS232::receiveDecodedData]File read error: " << strerror(errno) << std::endl;
//sleep(1);
}
nBytes += recvDataLen;
if(nBytes == ((int)recvBuffer[0] + 2))
break;
}
if(recvBuffer[1] == DECODE_DATA)
sendCommandToDecoder(OPCODE_ACK);
std::cout << "[INFO # DeviceRS232::receiveDecodedData]Data Lenght (without CheckSum) : " << (int)recvBuffer[0] << std::endl;
for(int i=0; i<nBytes; i++)
{
std::cout << "recvBuffer[" << i << "]: ";
printf("%x\n", recvBuffer[i]);
}
std::cout << "-----------------------------------" << std::endl;
ChangeRTS(fdRS232, 1);
ChangeCTS(fdRS232, 1);
//sleep(1);
}
//strcpy((char *)dataBuffer, (char *)recvBuffer);
memcpy((char *)dataBuffer, recvBuffer, sizeof(recvBuffer)/sizeof(recvBuffer[0]));
inputBufSize = 0;
return nBytes;
}
/**
* Send commands to the decoder.
*/
int DeviceRS232::sendCommandToDecoder(unsigned int opCode)
{
unsigned char *commandBuffer;
int commandLength;
switch(opCode)
{
case OPCODE_ACK:
{
unsigned char ackString[] = {0x00, 0xD0, 0x04, 0x00};
commandLength = sizeof(ackString);
commandBuffer = ackString;
}
break;
case OPCODE_PARAM_SEND:
{
unsigned char paramSendString[] = {0x00, 0xC6, 0x04, 0x08, 0x00, 0xEE, 0x01};
commandLength = sizeof(paramSendString);
commandBuffer = paramSendString;
}
break;
default:
break;
}
Message msgCommand(commandBuffer, commandLength);
return sendDataBuffer(msgCommand.getCommandData(), msgCommand.getLen());
}
Required constants defined in DeviceRS232.h header file.