Related
I want to read this sensor, it is an NPK Sensor. For this, I have this board, and this hat of this board to read the Mobus 485 link.
For this, the origin code that the hat gives us. To read the sensor I use the next tutorial, and finally the config of the NPK sensor:
Then after all of this, I generated this code:
#define PIN_5V_EN 0
#define CAN_TX_PIN 22
#define CAN_RX_PIN 21
#define RS485_TX_PIN 19
#define RS485_RX_PIN 18
#define RS485_EN_PIN 23
#define RE 23
#define DE 0
#include <Arduino.h>
#include <HardwareSerial.h>
#include <ModbusMaster.h>
// instantiate ModbusMaster object
ModbusMaster node;
HardwareSerial Serial485(2);
// Modbus RTU requests for reading NPK values
const byte water[] = {0x01, 0x03, 0x02, 0x01, 0x00, 0x01, 0xd4, 0x72};
const byte temp[] = {0x01, 0x03, 0x02, 0x00, 0x00, 0x01, 0x85, 0xb2};
const byte ec[] = {0x01, 0x03, 0x02, 0x02, 0x00, 0x01, 0x24, 0x72};
const byte ph[] = {0x01, 0x03, 0x02, 0x03, 0x00, 0x01, 0x75, 0xb2};
const byte nitro[] = {0x01, 0x03, 0x02, 0x04, 0x00, 0x01, 0xce, 0x73};
const byte phos[] = {0x01, 0x03, 0x02, 0x05, 0x00, 0x01, 0x95, 0xb3};
const byte pota[] = {0x01, 0x03, 0x02, 0x06, 0x00, 0x01, 0x65, 0xb3};
const byte dev_add[] = {0x01, 0x03, 0x10, 0x00, 0x00, 0x01, 0x80, 0xca};
const byte dev_baud[] = {0x01, 0x03, 0x10, 0x01, 0x00, 0x01, 0xd1, 0x0A};
// A variable used to store NPK values
byte values[11];
void CANTask(void *prarm);
void setup()
{
pinMode(RS485_EN_PIN, OUTPUT);
pinMode(PIN_5V_EN, OUTPUT);
Serial.begin(9600);
Serial485.begin(9600, SERIAL_8N1, RS485_RX_PIN, RS485_TX_PIN);
delay(5);
node.begin(2, Serial485);
}
void loop()
{
static uint32_t i;
uint8_t j, result;
uint16_t data[6];
byte val1,val2,val3,val4,val5,val6,val7,val8,val9;
val1 = water_func();
delay(250);
val2 = temperature();
delay(250);
val3 = ec_func();
delay(250);
val5 = ph_func();
delay(250);
val5 = nitrogen();
delay(250);
val6 = phosphorous();
delay(250);
val7 = potassium();
delay(250);
val8 = dev_add_func();
delay(250);
val9 = dev_baud_func();
delay(250);
// Print values to the serial monitor
Serial.print("Water: ");
Serial.print(val1);
Serial.println(" mg/kg");
Serial.print("Tempetature: ");
Serial.print(val2);
Serial.println(" ºC");
Serial.print("EC: ");
Serial.print(val3);
Serial.println(" mg/kg");
Serial.print("PH: ");
Serial.print(val4);
Serial.println(" mg/kg");
Serial.print("Nitrogen: ");
Serial.print(val5);
Serial.println(" mg/kg");
Serial.print("Phosphorous: ");
Serial.print(val6);
Serial.println(" mg/kg");
Serial.print("Potassium: ");
Serial.print(val7);
Serial.println(" mg/kg");
Serial.print("Devive_Address: ");
Serial.println(val8);
Serial.print("Devive_Baud: ");
Serial.println(val8);
delay(20000);
}
byte water_func(){
digitalWrite(DE,HIGH);
digitalWrite(RE,HIGH);
delay(10);
if(Serial485.write(water,sizeof(water))==8){
digitalWrite(DE,LOW);
digitalWrite(RE,LOW);
for(byte i=0;i<7;i++){
Serial.print(Serial485.read(),HEX);
values[i] = Serial485.read();
Serial.print(values[i],HEX);
}
Serial.println();
}
return values[4];
}
byte temperature(){
digitalWrite(DE,HIGH);
digitalWrite(RE,HIGH);
delay(10);
if(Serial485.write(temp,sizeof(temp))==8){
digitalWrite(DE,LOW);
digitalWrite(RE,LOW);
for(byte i=0;i<7;i++){
Serial.print(Serial485.read(),HEX);
values[i] = Serial485.read();
Serial.print(values[i],HEX);
}
Serial.println();
}
return values[4];
}
byte ec_func(){
digitalWrite(DE,HIGH);
digitalWrite(RE,HIGH);
delay(10);
if(Serial485.write(ec,sizeof(ec))==8){
digitalWrite(DE,LOW);
digitalWrite(RE,LOW);
for(byte i=0;i<7;i++){
Serial.print(Serial485.read(),HEX);
values[i] = Serial485.read();
Serial.print(values[i],HEX);
}
Serial.println();
}
return values[4];
}
byte ph_func(){
digitalWrite(DE,HIGH);
digitalWrite(RE,HIGH);
delay(10);
if(Serial485.write(ph,sizeof(ph))==8){
digitalWrite(DE,LOW);
digitalWrite(RE,LOW);
for(byte i=0;i<7;i++){
Serial.print(Serial485.read(),HEX);
values[i] = Serial485.read();
Serial.print(values[i],HEX);
}
Serial.println();
}
return values[4];
}
byte nitrogen(){
digitalWrite(DE,HIGH);
digitalWrite(RE,HIGH);
delay(10);
if(Serial485.write(nitro,sizeof(nitro))==8){
digitalWrite(DE,LOW);
digitalWrite(RE,LOW);
for(byte i=0;i<7;i++){
Serial.print(Serial485.read(),HEX);
values[i] = Serial485.read();
Serial.print(values[i],HEX);
}
Serial.println();
}
return values[4];
}
byte phosphorous(){
digitalWrite(DE,HIGH);
digitalWrite(RE,HIGH);
delay(10);
if(Serial485.write(phos,sizeof(phos))==8){
digitalWrite(DE,LOW);
digitalWrite(RE,LOW);
for(byte i=0;i<7;i++){
Serial.print(Serial485.read(),HEX);
values[i] = Serial485.read();
Serial.print(values[i],HEX);
}
Serial.println();
}
return values[4];
}
byte potassium(){
digitalWrite(DE,HIGH);
digitalWrite(RE,HIGH);
delay(10);
if(Serial485.write(pota,sizeof(pota))==8){
digitalWrite(DE,LOW);
digitalWrite(RE,LOW);
for(byte i=0;i<7;i++){
Serial.print(Serial485.read(),HEX);
values[i] = Serial485.read();
Serial.print(values[i],HEX);
}
Serial.println();
}
return values[4];
}
byte dev_add_func(){
digitalWrite(DE,HIGH);
digitalWrite(RE,HIGH);
delay(10);
if(Serial485.write(dev_add,sizeof(dev_add))==8){
digitalWrite(DE,LOW);
digitalWrite(RE,LOW);
for(byte i=0;i<7;i++){
Serial.print(Serial485.read(),HEX);
values[i] = Serial485.read();
Serial.print(values[i],HEX);
}
Serial.println();
}
return values[4];
}
byte dev_baud_func(){
digitalWrite(DE,HIGH);
digitalWrite(RE,HIGH);
delay(10);
if(Serial485.write(dev_baud,sizeof(dev_baud))==8){
digitalWrite(DE,LOW);
digitalWrite(RE,LOW);
for(byte i=0;i<7;i++){
Serial.print(Serial485.read(),HEX);
values[i] = Serial485.read();
Serial.print(values[i],HEX);
}
Serial.println();
}
return values[4];
}
But when I ran it, this is the output:
I think I have some issues with how to transmit the message and read it, any idea?
Thanks!!!
I don't have that sensor so be aware that I am guessing here but I can give you a couple of pointers that might help.
First of all, the datasheet for the sensor mentions the following:
The default baud rate is 4800bit / s and the default
address is 0x01
So the first thing to try is to select that baud rate:
Serial485.begin(4800, SERIAL_8N1, RS485_RX_PIN, RS485_TX_PIN);
I have no idea why the tutorial goes for 9600 baud but it seems wrong.
The next thing you need to realize is that you are doing some things in your code that are redundant. You are loading the ModbusMaster.h library but not using it. You are instead sending and receiving Modbus frames manually.
The easiest thing to do is just drop the library by removing these lines:
#include <ModbusMaster.h>
// instantiate ModbusMaster object
ModbusMaster node;
....
node.begin(2, Serial485);
But my preferred solution would be to actually use the library (do not reinvent the wheel, right?).
This is a short example to read temperature values from your sensor with ModbusMaster.h:
#define PIN_5V_EN 0
#define CAN_TX_PIN 22
#define CAN_RX_PIN 21
#define RS485_TX_PIN 19
#define RS485_RX_PIN 18
#define RS485_EN_PIN 23
#define RE 23
#define DE 0
#include <Arduino.h>
#include <HardwareSerial.h>
#include <ModbusMaster.h>
// instantiate ModbusMaster object
ModbusMaster node;
HardwareSerial Serial485(2);
// Modbus RTU requests for reading NPK values
// These are not needed, the library will do its magic
// A variable used to store NPK values
byte values[11];
void setup()
{
pinMode(RS485_EN_PIN, OUTPUT);
pinMode(PIN_5V_EN, OUTPUT);
Serial.begin(9600);
Serial485.begin(4800, SERIAL_8N1, RS485_RX_PIN, RS485_TX_PIN); // Changed to 4800, default value
delay(5);
node.begin(1, Serial485); // Changed to ID=1, default value
}
void loop()
{
uint8_t result;
uint16_t data_temperature;
result = node.readHoldingRegisters(0x0200, 1); // use library to read holding register 0x0200, just 1 register that contains the temperature
// do something with data if read is successful-->store
if (result == node.ku8MBSuccess) {
data_temperature = node.getResponseBuffer(0);
}
// Print values to the serial monitor
Serial.print("Tempetature: ");
Serial.print(data_temperature/100); //scale divinding by 100
Serial.println(" ºC");
delay(20000);
}
As you can see I've changed both the baud rate and the Modbus slave ID to 1 with node.begin(1, Serial485); to keep the default values as per the datasheet.
If you you use the library you don't have to take care of building, sending and receiving frames. Plus the CRCs are calculated and checked for you.
Finally, a couple of things that are really useful when you are debuggin a project like yours are:
A USB RS485 adaptor for your laptop/desktop computer. If you have one of these you can connect to your sensor using something like QModMaster then you can check the correct baud rate or what registers to read directly from a GUI instead of messing with code.
A scope makes the job much easier. You can check the wiring is correct and really see the frames running on the bus.
You can get a glimpse of how easy it easy to debug the configuration and map register of a Modbus device just following these steps (you should get the same temperature value you got using the Arduino code above):
-Download, extract and run QModMaster (qModMaster.exe). You might need to run as administrator.
-Set up your port selecting Modbus RTU from menu Options:
You might need to go to your Device Manager to check your port number. Other settings are the same as for your board.
-Save your settings by clicking OK. Now at the main window change Function Code to Read Holding Registers (0x03) and choose value 512 (0x0200) for Start Address , you should see something like this:
-Finally, go to Connect on menu Commands or click on the third icon starting from the left. Your temperature value (multiplied by 100) should appear on the first register (the box showing -/- just before connecting).
If you don't get the value, the only problem could be either something wrong with your sensor (power or otherwise) or a wiring issue. For my USB adaptor I'd have to connect A+, B- and GND (do not forget that one):
I did everything. I shutoff the bits to disable the output processing in the termios structure, properly set the baud rate and character size and disabled parity, flush the output and input buffers before sending. Even after all this linux serial still doesn't work the way I want it to. Canonical mode is not even on in the first place, everything is raw bytes. Btw I am using arch linux connected to an arduino nano with an usb cable which will receive the bytes from PC and display them on a lcd. When I send a byte from PC, e.g char 'A', it apears to get corrupted during the transmisson process, and arduino displays the corrupted byte. Everytime I send character 'A' it shows ascii value 254 on the lcd which is clearly wrong. How do I solve this problem?
My C code on pc:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>
int main(int argc, char **argv)
{
int serial_port = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
getchar();
struct termios old_tty;
struct termios new_tty;
if (tcgetattr(serial_port, &new_tty) != 0) {
printf("Error %i from tcgetattr: %s\n", errno, strerror(errno));
return 1;
}
old_tty = new_tty;
new_tty.c_cflag &= ~(CSTOPB | CSIZE | PARENB);
new_tty.c_cflag |= CS8;
new_tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
new_tty.c_oflag &= ~OPOST;
new_tty.c_iflag &= ~(IXON | IXOFF | IXANY | INPCK | ISTRIP);
//new_tty.c_cc[VMIN] = 0;
//new_tty.c_cc[VTIME] = 0;
cfsetispeed(&new_tty, B9600);
cfsetospeed(&new_tty, B9600);
if (tcsetattr(serial_port, TCSANOW, &new_tty) != 0) {
printf("Error %i from tcsetattr: %s\n", errno, strerror(errno));
return 1;
}
tcflush(serial_port, TCIOFLUSH);
unsigned char val = 'A';
write(serial_port, &val, sizeof(val));
getchar();
tcsetattr(serial_port, TCSANOW | TCSADRAIN, &old_tty);
close(serial_port);
return 0;
}
Code on Arduino:
void setup() {
lcd.begin(16, 2); // begins connection to the LCD module
lcd.backlight(); // turns on the backlight
lcd.clear();
lcd.setCursor(0, 0);
Serial.begin(9600);
lcd.print("Init done");
}
void loop() {
if (Serial.available() > 0) {
uint8_t x = Serial.read();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("I received: ");
lcd.setCursor(0, 1);
lcd.print(x);
}
}
I’m trying to write Android Uno code to send HEX values via SoftwareSerial but when watching the Serial Monitor the output isn’t what I expected or wanted, and I am not experienced enough yet to know what to do next.
I don’t know where the FFFFs come from to be able to eliminate them.
My desired output is:
<br>
AA130120<br>
AA0400AE
What I get is:
<br>
FFFFFFFFAA1311E<br>
FFFFFFAA20
My code:
#include <SoftwareSerial.h>
// Define the RX and TX pins to establish UART communication with the MP3 Player Module.
#define Pin_RX 0 // to RX
#define Pin_TX 1 // to TX
#define d_sleep 10000
// Define the required MP3 Player Commands:
static byte ccPlay[] = {0xAA, 0x02, 0x00, 0xAC}; // Play:
static byte ccSetVol[] = {0xAA, 0x13, 0x01, 0x20}; // Set Volume (00-30):
// Define the Serial MP3 Player Module.
SoftwareSerial MP3(Pin_RX, Pin_TX);
void setup() {
// Initiate the serial monitor.
Serial.begin(9600);
}
void loop() { // Play a song.
ccSetVol[3] = {0x1E};
send_command_to_MP3_player(ccSetVol, 4);
delay(d_sleep);
send_command_to_MP3_player(ccPlay, 4);
delay(d_sleep);
}
void send_command_to_MP3_player(int8_t command[], int len){
//Serial.print("\nMP3 Command => ");
for (int i=0; i<len; i++) {
MP3.write(command[i]);
Serial.print(command[i], HEX);
}
delay(100);
}
Could you set the baud rate in the serial monitor to 9600Bd, run this code, and see if it spits out the bytes you expect in the serial monitor?
#define d_sleep 10000
static byte ccPlay[] = {0xAA, 0x02, 0x00, 0xAC};
static byte ccSetVol[] = {0xAA, 0x13, 0x01, 0x20};
void send_command_to_MP3_player(byte command[], int len) {
for (int i=0; i<len; i++) {
//Serial.println(command[i], HEX);
Serial.print(command[i], HEX);
}
//Serial.println();
delay(100);
}
void setup() {
Serial.begin(9600);
delay(1500);
}
void loop() {
ccSetVol[3] = 0x1E;
send_command_to_MP3_player(ccSetVol, 4);
delay(d_sleep);
send_command_to_MP3_player(ccPlay, 4);
delay(d_sleep);
}
I need your help for a project.
I have actually 2 parallel sensors of the type: MS5803-05BA, which supports I2C and SPI connection. One sensor is on I2C bus and one sensor is on SPI. They are both sending to my Arduino Mega. The I2C works perfect with short cables.
Here the datasheet of the sensor:
https://www.amsys.de/downloads/data/MS5803-05BA-AMSYS-datasheet.pdf
For some informations who wants to do the same with I2C. Here you can find a good code. (You can find the other MS580X typs there too). For the communication between the sensor and the Arduino Mega you need an logic converter like this txs0108e, which can be bought with a break out board (you need pull up resistors on the sensor side!):
https://github.com/millerlp/MS5803_05
But to my problem: I have an sensor distance for about 3-5 meters and the I2C connections doesnt work. Yes I can try to fix the pullup resistors but it doesnt worked for me (I have tried some different lower resistors between 3-10kOhm). Therefore I want to switch to the SPI bus.
I have edit the code from https://github.com/millerlp/MS5803_05, https://github.com/vic320/Arduino-MS5803-14BA and https://arduino.stackexchange.com/questions/13720/teensy-spi-and-pressure-sensor.
The File is added. (You have to put the .h and .cpp files in the folder of the arduino code (.spi).
I have problems with the code from the SPI (ccp and header). There is no right communication. I have checked my cables twice. I couldnt find a problem and the connection with the txs0108e works for parallel I2C sensor. Both sensors are working on I2C.
Here is the main code (arduino .spi) for SPI and I2C parallel:
/_____ I N C L U D E S
#include <stdio.h>
#include <math.h>
#include <SPI.h>
#include <Wire.h>
#include "MS5803_05.h"
#include "MS5803_05_SPI.h"
const int miso_port = 50; //SDI
const int mosi_port = 51; //SDO
const int sck_port = 52; //SLCK
const int slaveSelectPin = 53; // CSB
MS_5803 sensor = MS_5803(512);
MS_5803_SPI sensor_spi = MS_5803_SPI(4096, slaveSelectPin);
void setup()
{
pinMode(miso_port, INPUT);
pinMode(mosi_port, OUTPUT);
pinMode(slaveSelectPin, OUTPUT);
pinMode(sck_port, OUTPUT);
Serial.begin(9600);
//SPI BUS
if (sensor_spi.initializeMS_5803_SPI()) {
Serial.println( "MS5803 SPI CRC check OK." );
}
else {
Serial.println( "MS5803 SPI CRC check FAILED!" );
}
//I2C BUS
delay(1000);
if (sensor.initializeMS_5803()) {
Serial.println( "MS5803 I2C CRC check OK." );
}
else {
Serial.println( "MS5803 I2C CRC check FAILED!" );
}
}
void loop()
{
Serial.println("SPI Sensor first pressure [mbar], than temperature[°C]:");
sensor_spi.readSensor();
// Show pressure
Serial.print("Pressure = ");
Serial.print(sensor_spi.pressure());
Serial.println(" mbar");
// Show temperature
Serial.print("Temperature = ");
Serial.print(sensor_spi.temperature());
Serial.println("C");
////********************************************************
Serial.println("");
Serial.println("I2C Sensor first pressure [mbar], than temperature[°C]:");
sensor.readSensor();
// Show pressure
Serial.print("Pressure = ");
Serial.print(sensor.pressure());
Serial.println(" mbar");
// Show temperature
Serial.print("Temperature = ");
Serial.print(sensor.temperature());
Serial.println("C");
delay(2000);
}
}
The first connection with SPI is here (.cpp):
#include "MS5803_05_SPI.h"
#include <SPI.h>
#define CMD_RESET 0x1E // ADC reset command
#define CMD_ADC_READ 0x00 // ADC read command
#define CMD_ADC_CONV 0x40 // ADC conversion command
#define CMD_ADC_D1 0x00 // ADC D1 conversion
#define CMD_ADC_D2 0x10 // ADC D2 conversion
#define CMD_ADC_256 0x00 // ADC resolution=256
#define CMD_ADC_512 0x02 // ADC resolution=512
#define CMD_ADC_1024 0x04 // ADC resolution=1024
#define CMD_ADC_2048 0x06 // ADC resolution=2048
#define CMD_ADC_4096 0x08 // ADC resolution=4096
#define CMD_PROM_RD 0xA0 // Prom read command
#define spi_write SPI_MODE3
#define spi_write2 SPI_MODE1
// Create array to hold the 8 sensor calibration coefficients
static unsigned int sensorCoeffs[8]; // unsigned 16-bit integer (0-65535)
// D1 and D2 need to be unsigned 32-bit integers (long 0-4294967295)
static uint32_t D1 = 0; // Store uncompensated pressure value
static uint32_t D2 = 0; // Store uncompensated temperature value
// These three variables are used for the conversion steps
// They should be signed 32-bit integer initially
// i.e. signed long from -2147483648 to 2147483647
static int32_t dT = 0;
static int32_t TEMP = 0;
// These values need to be signed 64 bit integers
// (long long = int64_t)
static int64_t Offset = 0;
static int64_t Sensitivity = 0;
static int64_t T2 = 0;
static int64_t OFF2 = 0;
static int64_t Sens2 = 0;
// Some constants used in calculations below
const uint64_t POW_2_33 = 8589934592ULL; // 2^33 = 8589934592
SPISettings settings_write(500000, MSBFIRST, spi_write);
SPISettings settings_write2(500000, MSBFIRST, spi_write2);
//-------------------------------------------------
// Constructor
MS_5803_SPI::MS_5803_SPI( uint16_t Resolution, uint16_t cs) {
// The argument is the oversampling resolution, which may have values
// of 256, 512, 1024, 2048, or 4096.
_Resolution = Resolution;
//Chip Select
_cs=cs;
}
boolean MS_5803_SPI::initializeMS_5803_SPI(boolean Verbose) {
digitalWrite( _cs, HIGH );
SPI.begin();
// Reset the sensor during startup
resetSensor();
if (Verbose)
{
// Display the oversampling resolution or an error message
if (_Resolution == 256 | _Resolution == 512 | _Resolution == 1024 | _Resolution == 2048 | _Resolution == 4096){
Serial.print("Oversampling setting: ");
Serial.println(_Resolution);
} else {
Serial.println("*******************************************");
Serial.println("Error: specify a valid oversampling value");
Serial.println("Choices are 256, 512, 1024, 2048, or 4096");
Serial.println("*******************************************");
}
}
// Read sensor coefficients
for (int i = 0; i < 8; i++ )
{
SPI.beginTransaction(settings_write2);
digitalWrite(_cs, LOW); //csb_lo(); // pull CSB low
unsigned int ret;
unsigned int rC = 0;
SPI.transfer(CMD_PROM_RD + i * 2); // send PROM READ command
/*
ret = SPI.transfer(0x00); // send 0 to read the MSB
rC = 256 * ret;
ret = SPI.transfer(0x00); // send 0 to read the LSB
rC = rC + ret;
*/
// send a value of 0 to read the first byte returned:
rC = SPI.transfer( 0x00 );
rC = rC << 8;
rC |= SPI.transfer( 0x00 ); // and the second byte
sensorCoeffs[i] = (rC);
digitalWrite( _cs, HIGH );
delay(3);
}
//SPI.endTransaction(); // interrupt can now be accepted
// The last 4 bits of the 7th coefficient form a CRC error checking code.
unsigned char p_crc = sensorCoeffs[7];
// Use a function to calculate the CRC value
unsigned char n_crc = MS_5803_CRC(sensorCoeffs);
if (Verbose) {
for (int i = 0; i < 8; i++ )
{
// Print out coefficients
Serial.print("C");
Serial.print(i);
Serial.print(" = ");
Serial.println(sensorCoeffs[i]);
delay(10);
}
Serial.print("p_crc: ");
Serial.println(p_crc);
Serial.print("n_crc: ");
Serial.println(n_crc);
}
// If the CRC value doesn't match the sensor's CRC value, then the
// connection can't be trusted. Check your wiring.
if (p_crc != n_crc) {
return false;
}
// Otherwise, return true when everything checks out OK.
return true;
}
// Sends a power on reset command to the sensor.
void MS_5803_SPI::resetSensor() {
SPI.beginTransaction(settings_write);
digitalWrite(_cs, LOW); //csb_lo(); // pull CSB low to start the command
SPI.transfer(CMD_RESET); // send reset sequence
delay(3); // wait for the reset sequence timing delay(3)
digitalWrite(_cs, HIGH); //csb_hi(); // pull CSB high to finish the command
SPI.endTransaction(); // interrupt can now be accepted
}
The Code can be downloaded at: https://forum.arduino.cc/index.php?topic=670661.0
There you can find the schematic and output picture too.
Thanks a lot :).
I am using this NFC Shield http://www.elecfreaks.com/wiki/index.php?title=RFID_/_NFC_Shield
and by using the provided library I am not able to run the examples.
This is the example code.
#include <PN532.h>
#define SCK 13
#define MOSI 11
#define SS 10
#define MISO 12
PN532 nfc(SCK, MISO, MOSI, SS);
void setup(void) {
Serial.begin(9600);
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);
Serial.print("Supports "); Serial.println(versiondata & 0xFF, HEX);
// configure board to read RFID tags and cards
nfc.SAMConfig();
}
void loop(void) {
uint32_t id;
// look for MiFare type cards
id = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A);
if (id != 0) {
Serial.print("Read card #"); Serial.println(id);
}
}
and it gives this error
http://i.stack.imgur.com/MNvl9.jpg
And these are the detailed errors
In file included from readMifareTargetID.pde:1:
C:\Users\saqib\Documents\Arduino\libraries\PN532_SPI/PN532.h:44: error: expected `)' before 'cs'
C:\Users\saqib\Documents\Arduino\libraries\PN532_SPI/PN532.h:48: error: 'boolean' does not name a type
C:\Users\saqib\Documents\Arduino\libraries\PN532_SPI/PN532.h:49: error: 'uint32_t' does not name a type
C:\Users\saqib\Documents\Arduino\libraries\PN532_SPI/PN532.h:50: error: 'uint32_t' does not name a type
C:\Users\saqib\Documents\Arduino\libraries\PN532_SPI/PN532.h:51: error: 'uint32_t' does not name a type
C:\Users\saqib\Documents\Arduino\libraries\PN532_SPI/PN532.h:57: error: 'uint32_t' does not name a type
C:\Users\saqib\Documents\Arduino\libraries\PN532_SPI/PN532.h:58: error: 'uint32_t' does not name a type
C:\Users\saqib\Documents\Arduino\libraries\PN532_SPI/PN532.h:60: error: 'boolean' does not name a type
C:\Users\saqib\Documents\Arduino\libraries\PN532_SPI/PN532.h:65: error: 'uint8_t' does not name a type
C:\Users\saqib\Documents\Arduino\libraries\PN532_SPI/PN532.h:67: error: 'boolean' does not name a type
C:\Users\saqib\Documents\Arduino\libraries\PN532_SPI/PN532.h:68: error: 'uint8_t' does not name a type
C:\Users\saqib\Documents\Arduino\libraries\PN532_SPI/PN532.h:69: error: 'uint8_t' has not been declared
C:\Users\saqib\Documents\Arduino\libraries\PN532_SPI/PN532.h:69: error: 'uint8_t' has not been declared
C:\Users\saqib\Documents\Arduino\libraries\PN532_SPI/PN532.h:70: error: 'uint8_t' has not been declared
C:\Users\saqib\Documents\Arduino\libraries\PN532_SPI/PN532.h:70: error: 'uint8_t' has not been declared
C:\Users\saqib\Documents\Arduino\libraries\PN532_SPI/PN532.h:71: error: 'uint8_t' has not been declared
C:\Users\saqib\Documents\Arduino\libraries\PN532_SPI/PN532.h:72: error: 'uint8_t' does not name a type
In file included from C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino/Arduino.h:213,
from readMifareTargetID.pde:8:
C:\Program Files (x86)\Arduino\hardware\arduino\variants\mega/pins_arduino.h:35: error: expected unqualified-id before numeric constant
C:\Program Files (x86)\Arduino\hardware\arduino\variants\mega/pins_arduino.h:36: error: expected unqualified-id before numeric constant
C:\Program Files (x86)\Arduino\hardware\arduino\variants\mega/pins_arduino.h:37: error: expected unqualified-id before numeric constant
C:\Program Files (x86)\Arduino\hardware\arduino\variants\mega/pins_arduino.h:38: error: expected unqualified-id before numeric constant
readMifareTargetID:8: error: no matching function for call to 'PN532::PN532(int, int, int, int)'
C:\Users\saqib\Documents\Arduino\libraries\PN532_SPI/PN532.h:42: note: candidates are: PN532::PN532()
C:\Users\saqib\Documents\Arduino\libraries\PN532_SPI/PN532.h:42: note: PN532::PN532(const PN532&)
readMifareTargetID.pde: In function 'void setup()':
readMifareTargetID:16: error: 'class PN532' has no member named 'getFirmwareVersion'
readMifareTargetID:28: error: 'class PN532' has no member named 'SAMConfig'
readMifareTargetID.pde: In function 'void loop()':
readMifareTargetID:35: error: 'class PN532' has no member named 'readPassiveTargetID'
This is the .h file with the library
// PN532 library by adafruit/ladyada
// MIT license
// authenticateBlock, readMemoryBlock, writeMemoryBlock contributed
// by Seeed Technology Inc (www.seeedstudio.com)
#include <Arduino.h>
#define PN532_PREAMBLE 0x00
#define PN532_STARTCODE1 0x00
#define PN532_STARTCODE2 0xFF
#define PN532_POSTAMBLE 0x00
#define PN532_HOSTTOPN532 0xD4
#define PN532_FIRMWAREVERSION 0x02
#define PN532_GETGENERALSTATUS 0x04
#define PN532_SAMCONFIGURATION 0x14
#define PN532_INLISTPASSIVETARGET 0x4A
#define PN532_INDATAEXCHANGE 0x40
#define PN532_MIFARE_READ 0x30
#define PN532_MIFARE_WRITE 0xA0
#define PN532_AUTH_WITH_KEYA 0x60
#define PN532_AUTH_WITH_KEYB 0x61
#define PN532_WAKEUP 0x55
#define PN532_SPI_STATREAD 0x02
#define PN532_SPI_DATAWRITE 0x01
#define PN532_SPI_DATAREAD 0x03
#define PN532_SPI_READY 0x01
#define PN532_MIFARE_ISO14443A 0x0
#define KEY_A 1
#define KEY_B 2
class PN532{
public:
PN532(uint8_t cs, uint8_t clk, uint8_t mosi, uint8_t miso);
void begin(void);
boolean SAMConfig(void);
uint32_t getFirmwareVersion(void);
uint32_t readPassiveTargetID(uint8_t cardbaudrate);
uint32_t authenticateBlock( uint8_t cardnumber /*1 or 2*/,
uint32_t cid /*Card NUID*/,
uint8_t blockaddress /*0 to 63*/,
uint8_t authtype /*Either KEY_A or KEY_B */,
uint8_t * keys);
uint32_t readMemoryBlock(uint8_t cardnumber /*1 or 2*/,uint8_t blockaddress /*0 to 63*/, uint8_t * block);
uint32_t writeMemoryBlock(uint8_t cardnumber /*1 or 2*/,uint8_t blockaddress /*0 to 63*/, uint8_t * block);
boolean sendCommandCheckAck(uint8_t *cmd, uint8_t cmdlen, uint16_t timeout = 1000);
//
private:
uint8_t _ss, _clk, _mosi, _miso;
boolean spi_readack();
uint8_t readspistatus(void);
void readspidata(uint8_t* buff, uint8_t n);
void spiwritecommand(uint8_t* cmd, uint8_t cmdlen);
void spiwrite(uint8_t c);
uint8_t spiread(void);
};
and this the .cpp file
// PN532 library by adafruit/ladyada
// MIT license
// authenticateBlock, readMemoryBlock, writeMemoryBlock contributed
// by Seeed Technology Inc (www.seeedstudio.com)
#include <Arduino.h>
#include "PN532.h"
//#define PN532DEBUG 1
byte pn532ack[] = {0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00};
byte pn532response_firmwarevers[] = {0x00, 0xFF, 0x06, 0xFA, 0xD5, 0x03};
#define PN532_PACKBUFFSIZ 64
byte pn532_packetbuffer[PN532_PACKBUFFSIZ];
PN532::PN532(uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t ss) {
_clk = clk;
_miso = miso;
_mosi = mosi;
_ss = ss;
pinMode(_ss, OUTPUT);
pinMode(_clk, OUTPUT);
pinMode(_mosi, OUTPUT);
pinMode(_miso, INPUT);
}
void PN532::begin() {
digitalWrite(_ss, LOW);
delay(1000);
// not exactly sure why but we have to send a dummy command to get synced up
pn532_packetbuffer[0] = PN532_FIRMWAREVERSION;
sendCommandCheckAck(pn532_packetbuffer, 1);
// ignore response!
}
uint32_t PN532::getFirmwareVersion(void) {
uint32_t response;
pn532_packetbuffer[0] = PN532_FIRMWAREVERSION;
if (! sendCommandCheckAck(pn532_packetbuffer, 1))
return 0;
// read data packet
readspidata(pn532_packetbuffer, 12);
// check some basic stuff
if (0 != strncmp((char *)pn532_packetbuffer, (char *)pn532response_firmwarevers, 6)) {
return 0;
}
response = pn532_packetbuffer[6];
response <<= 8;
response |= pn532_packetbuffer[7];
response <<= 8;
response |= pn532_packetbuffer[8];
response <<= 8;
response |= pn532_packetbuffer[9];
return response;
}
// default timeout of one second
boolean PN532::sendCommandCheckAck(uint8_t *cmd, uint8_t cmdlen, uint16_t timeout) {
uint16_t timer = 0;
// write the command
spiwritecommand(cmd, cmdlen);
// Wait for chip to say its ready!
while (readspistatus() != PN532_SPI_READY) {
if (timeout != 0) {
timer+=10;
if (timer > timeout)
return false;
}
delay(10);
}
// read acknowledgement
if (!spi_readack()) {
return false;
}
timer = 0;
// Wait for chip to say its ready!
while (readspistatus() != PN532_SPI_READY) {
if (timeout != 0) {
timer+=10;
if (timer > timeout)
return false;
}
delay(10);
}
return true; // ack'd command
}
boolean PN532::SAMConfig(void) {
pn532_packetbuffer[0] = PN532_SAMCONFIGURATION;
pn532_packetbuffer[1] = 0x01; // normal mode;
pn532_packetbuffer[2] = 0x14; // timeout 50ms * 20 = 1 second
pn532_packetbuffer[3] = 0x01; // use IRQ pin!
if (! sendCommandCheckAck(pn532_packetbuffer, 4))
return false;
// read data packet
readspidata(pn532_packetbuffer, 8);
return (pn532_packetbuffer[5] == 0x15);
}
uint32_t PN532::authenticateBlock(uint8_t cardnumber /*1 or 2*/,uint32_t cid /*Card NUID*/, uint8_t blockaddress /*0 to 63*/,uint8_t authtype/*Either KEY_A or KEY_B */, uint8_t * keys) {
pn532_packetbuffer[0] = PN532_INDATAEXCHANGE;
pn532_packetbuffer[1] = cardnumber; // either card 1 or 2 (tested for card 1)
if(authtype == KEY_A)
{
pn532_packetbuffer[2] = PN532_AUTH_WITH_KEYA;
}
else
{
pn532_packetbuffer[2] = PN532_AUTH_WITH_KEYB;
}
pn532_packetbuffer[3] = blockaddress; //This address can be 0-63 for MIFARE 1K card
pn532_packetbuffer[4] = keys[0];
pn532_packetbuffer[5] = keys[1];
pn532_packetbuffer[6] = keys[2];
pn532_packetbuffer[7] = keys[3];
pn532_packetbuffer[8] = keys[4];
pn532_packetbuffer[9] = keys[5];
pn532_packetbuffer[10] = ((cid >> 24) & 0xFF);
pn532_packetbuffer[11] = ((cid >> 16) & 0xFF);
pn532_packetbuffer[12] = ((cid >> 8) & 0xFF);
pn532_packetbuffer[13] = ((cid >> 0) & 0xFF);
if (! sendCommandCheckAck(pn532_packetbuffer, 14))
return false;
// read data packet
readspidata(pn532_packetbuffer, 2+6);
#ifdef PN532DEBUG
for(int iter=0;iter<14;iter++)
{
Serial.print(pn532_packetbuffer[iter], HEX);
Serial.print(" ");
}
Serial.println();
// check some basic stuff
Serial.println("AUTH");
for(uint8_t i=0;i<2+6;i++)
{
Serial.print(pn532_packetbuffer[i], HEX); Serial.println(" ");
}
#endif
if((pn532_packetbuffer[6] == 0x41) && (pn532_packetbuffer[7] == 0x00))
{
return true;
}
else
{
return false;
}
}
uint32_t PN532::readMemoryBlock(uint8_t cardnumber /*1 or 2*/,uint8_t blockaddress /*0 to 63*/, uint8_t * block) {
pn532_packetbuffer[0] = PN532_INDATAEXCHANGE;
pn532_packetbuffer[1] = cardnumber; // either card 1 or 2 (tested for card 1)
pn532_packetbuffer[2] = PN532_MIFARE_READ;
pn532_packetbuffer[3] = blockaddress; //This address can be 0-63 for MIFARE 1K card
if (! sendCommandCheckAck(pn532_packetbuffer, 4))
return false;
// read data packet
readspidata(pn532_packetbuffer, 18+6);
// check some basic stuff
#ifdef PN532DEBUG
Serial.println("READ");
#endif
for(uint8_t i=8;i<18+6;i++)
{
block[i-8] = pn532_packetbuffer[i];
#ifdef PN532DEBUG
Serial.print(pn532_packetbuffer[i], HEX); Serial.print(" ");
#endif
}
if((pn532_packetbuffer[6] == 0x41) && (pn532_packetbuffer[7] == 0x00))
{
return true; //read successful
}
else
{
return false;
}
}
//Do not write to Sector Trailer Block unless you know what you are doing.
uint32_t PN532::writeMemoryBlock(uint8_t cardnumber /*1 or 2*/,uint8_t blockaddress /*0 to 63*/, uint8_t * block) {
pn532_packetbuffer[0] = PN532_INDATAEXCHANGE;
pn532_packetbuffer[1] = cardnumber; // either card 1 or 2 (tested for card 1)
pn532_packetbuffer[2] = PN532_MIFARE_WRITE;
pn532_packetbuffer[3] = blockaddress;
for(uint8_t byte=0; byte <16; byte++)
{
pn532_packetbuffer[4+byte] = block[byte];
}
if (! sendCommandCheckAck(pn532_packetbuffer, 20))
return false;
// read data packet
readspidata(pn532_packetbuffer, 2+6);
#ifdef PN532DEBUG
// check some basic stuff
Serial.println("WRITE");
for(uint8_t i=0;i<2+6;i++)
{
Serial.print(pn532_packetbuffer[i], HEX); Serial.println(" ");
}
#endif
if((pn532_packetbuffer[6] == 0x41) && (pn532_packetbuffer[7] == 0x00))
{
return true; //write successful
}
else
{
return false;
}
}
uint32_t PN532::readPassiveTargetID(uint8_t cardbaudrate) {
uint32_t cid;
pn532_packetbuffer[0] = PN532_INLISTPASSIVETARGET;
pn532_packetbuffer[1] = 1; // max 1 cards at once (we can set this to 2 later)
pn532_packetbuffer[2] = cardbaudrate;
if (! sendCommandCheckAck(pn532_packetbuffer, 3))
return 0x0; // no cards read
// read data packet
readspidata(pn532_packetbuffer, 20);
// check some basic stuff
Serial.print("Found "); Serial.print(pn532_packetbuffer[7], DEC); Serial.println(" tags");
if (pn532_packetbuffer[7] != 1)
return 0;
uint16_t sens_res = pn532_packetbuffer[9];
sens_res <<= 8;
sens_res |= pn532_packetbuffer[10];
Serial.print("Sens Response: 0x"); Serial.println(sens_res, HEX);
Serial.print("Sel Response: 0x"); Serial.println(pn532_packetbuffer[11], HEX);
cid = 0;
for (uint8_t i=0; i< pn532_packetbuffer[12]; i++) {
cid <<= 8;
cid |= pn532_packetbuffer[13+i];
Serial.print(" 0x"); Serial.print(pn532_packetbuffer[13+i], HEX);
}
#ifdef PN532DEBUG
Serial.println("TargetID");
for(uint8_t i=0;i<20;i++)
{
Serial.print(pn532_packetbuffer[i], HEX); Serial.println(" ");
}
#endif
return cid;
}
/************** high level SPI */
boolean PN532::spi_readack() {
uint8_t ackbuff[6];
readspidata(ackbuff, 6);
return (0 == strncmp((char *)ackbuff, (char *)pn532ack, 6));
}
/************** mid level SPI */
uint8_t PN532::readspistatus(void) {
digitalWrite(_ss, LOW);
delay(2);
spiwrite(PN532_SPI_STATREAD);
// read byte
uint8_t x = spiread();
digitalWrite(_ss, HIGH);
return x;
}
void PN532::readspidata(uint8_t* buff, uint8_t n) {
digitalWrite(_ss, LOW);
delay(2);
spiwrite(PN532_SPI_DATAREAD);
#ifdef PN532DEBUG
Serial.print("Reading: ");
#endif
for (uint8_t i=0; i<n; i++) {
delay(1);
buff[i] = spiread();
#ifdef PN532DEBUG
Serial.print(" 0x");
Serial.print(buff[i], HEX);
#endif
}
#ifdef PN532DEBUG
Serial.println();
#endif
digitalWrite(_ss, HIGH);
}
void PN532::spiwritecommand(uint8_t* cmd, uint8_t cmdlen) {
uint8_t checksum;
cmdlen++;
#ifdef PN532DEBUG
Serial.print("\nSending: ");
#endif
digitalWrite(_ss, LOW);
delay(2); // or whatever the delay is for waking up the board
spiwrite(PN532_SPI_DATAWRITE);
checksum = PN532_PREAMBLE + PN532_PREAMBLE + PN532_STARTCODE2;
spiwrite(PN532_PREAMBLE);
spiwrite(PN532_PREAMBLE);
spiwrite(PN532_STARTCODE2);
spiwrite(cmdlen);
uint8_t cmdlen_1=~cmdlen + 1;
spiwrite(cmdlen_1);
spiwrite(PN532_HOSTTOPN532);
checksum += PN532_HOSTTOPN532;
#ifdef PN532DEBUG
Serial.print(" 0x"); Serial.print(PN532_PREAMBLE, HEX);
Serial.print(" 0x"); Serial.print(PN532_PREAMBLE, HEX);
Serial.print(" 0x"); Serial.print(PN532_STARTCODE2, HEX);
Serial.print(" 0x"); Serial.print(cmdlen, HEX);
Serial.print(" 0x"); Serial.print(cmdlen_1, HEX);
Serial.print(" 0x"); Serial.print(PN532_HOSTTOPN532, HEX);
#endif
for (uint8_t i=0; i<cmdlen-1; i++) {
spiwrite(cmd[i]);
checksum += cmd[i];
#ifdef PN532DEBUG
Serial.print(" 0x"); Serial.print(cmd[i], HEX);
#endif
}
uint8_t checksum_1=~checksum;
spiwrite(checksum_1);
spiwrite(PN532_POSTAMBLE);
digitalWrite(_ss, HIGH);
#ifdef PN532DEBUG
Serial.print(" 0x"); Serial.print(checksum_1, HEX);
Serial.print(" 0x"); Serial.print(PN532_POSTAMBLE, HEX);
Serial.println();
#endif
}
/************** low level SPI */
void PN532::spiwrite(uint8_t c) {
int8_t i;
digitalWrite(_clk, HIGH);
for (i=0; i<8; i++) {
digitalWrite(_clk, LOW);
if (c & _BV(i)) {
digitalWrite(_mosi, HIGH);
} else {
digitalWrite(_mosi, LOW);
}
digitalWrite(_clk, HIGH);
}
}
uint8_t PN532::spiread(void) {
int8_t i, x;
x = 0;
digitalWrite(_clk, HIGH);
for (i=0; i<8; i++) {
if (digitalRead(_miso)) {
x |= _BV(i);
}
digitalWrite(_clk, LOW);
digitalWrite(_clk, HIGH);
}
return x;
}
I am a beginner and any help will be greatly appreciated.Thanks
you're not including the stdlib and stdbool headers that give you respectively the uint8_t/uint32_t type and boolean type, please consider adding this at the top of your files:
#include <stdint.h>
#include <stdbool.h>
Dont exactly know how it happened but I did try some things that I would like to mention which may help somebody else with this problem.
I deleted all my libraries of NFC(PN532) and added the original library using Arduino's own add library option.
Other than that I just changed my board to Uno and then changed it back to 2560 mega and compiled the sketch and it works now.
Note:(FOR ANYBODY NEW WHO READS THIS) Anybody using Arduino 1.0 or greater for such libraries should edit the .h and .cpp files by removing WProgram.h with Arduino.h.