Arduino Modbus RTU Response over serial? - arduino

I am developing a project where I have to read the holding registers data. I check everything using this http://www.freemodbus.com/ and it is working and get a proper response. While trying with the developed program I am not getting the proper response.
Software Response: 0x01 0x03 0x04 0x1a 0xa0 0x42 0x48 0xcd 0x9f
Arduino response: 0x01 0x04 0x83 0x43 0xff 0xff 0xff 0xff 0xff
note that in Arduino response there is no 0x03 after 0x01 I don't know why it is happening can anyone please help me with this.
please find attached Arduino code below.
static union
{
unsigned long a;
byte b[4];
float f;
}vr;
void readregister(unsigned int address)
{
byte rxbuf[]={0,0,0,0,0,0,0,0,0,0,0};
byte data[] = {0x01,0x03,0x00,0xab,0x00,0x02,0xb5,0xeb};
Serial3.flush();
for(int i=0;i<8;i++)
{
Serial3.write(data[i]);
}
delay(250);
while(Serial3.available()>0)
{
for(int v=0; v<=10;v++)
{
rxbuf[v]=Serial3.read();
Serial.println(rxbuf[v],HEX);
}
}
Serial3.flush();
vr.b[3]=rxbuf[3];
vr.b[2]=rxbuf[2];
vr.b[1]=rxbuf[5];
vr.b[0]=rxbuf[4];
}
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Serial3.begin(9600,SERIAL_8E1);
}
void loop() {
// put your main code here, to run repeatedly:
readregister(99);
Serial.print("\n");
delay(3000);
}

Yes, I think you're getting an Error code 4 back from the device. See http://www.simplymodbus.ca/exceptions.htm
On this line, where you prep your request:
byte data[] = {0x01,0x03,0x00,0xab,0x00,0x02,0xb5,0xeb};
You're saying, device 1, function 3, 0x00 is space, then register address 0xAB. Not sure about the extra zero then, then length 2, and then CRC. So I vote that either the CRC is wrong, or the extra zero is wrong.
Also, note that modbus fails on ocassion for no reason, even when you do everything right, so retry after a few seconds and see what happens

Related

GPS module on ESP32 not giving valid logs

Environments
osx
esp32
vscode
platformio
I am working on an ESP32 module with this GPS module (very similar except the one I have has "ublox" logo on it - bought about 2 years ago).
#include <Arduino.h>
#include <HardwareSerial.h>
#include <TinyGPS++.h>
TinyGPSPlus gps;
HardwareSerial SerialGPS(2);
void setup() {
Serial.begin(115200); // RX TX
SerialGPS.begin(9600, SERIAL_8N1, 16, 17);
}
void loop() {
Serial.println("------------");
Serial.print("available(): ");
Serial.println(SerialGPS.available());
Serial.println("------------");
while (SerialGPS.available() > 0) {
char c = SerialGPS.read();
Serial.print(c);
gps.encode(c);
}
Serial.println();
if (gps.location.isValid()) {
Serial.print("LAT=");
Serial.println(gps.location.lat(), 6);
Serial.print("LONG=");
Serial.println(gps.location.lng(), 6);
Serial.print("ALT=");
Serial.println(gps.altitude.meters());
} else {
Serial.println("not valid");
}
delay(1000);
}
I took it outside and ran it for over 15 mins, and I see the data are still invalid.
------------
available(): 195
------------
$GPRMC,023424.00,V,,,,,,,051120,,,N*79
$GPVTG,,,,,,,,,N*30
$GPGGA,023424.00,,,,,0,00,99.99,,,,,,*65
$GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30
$GPGSV,1,1,00*79
$GPGLL,,,,,023424.00,V,N*49
not valid
------------
available(): 195
------------
$GPRMC,023425.00,V,,,,,,,051120,,,N*78
$GPVTG,,,,,,,,,N*30
$GPGGA,023425.00,,,,,0,00,99.99,,,,,,*64
$GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30
$GPGSV,1,1,00*79
$GPGLL,,,,,023425.00,V,N*48
not valid
Since I see letters coming in, I don't think TX and RX are mixed up.
I am giving it 5V (although not exactly sure if it should be 3.3v or 5v).
How can I get valid GPS data coming in from this module?
To me it looks like the GPS module is sending data properly, but hasn't got any available. It could still be looking for satellites. You can try printing the number of available ones, and simply wait longer:
Add the following lines to your program before your if statement:
Serial.println(gps.time.value()); // Raw time in HHMMSSCC format (u32)
Serial.println(gps.time.hour()); // Hour (0-23) (u8)
Serial.println(gps.time.minute()); // Minute (0-59) (u8)
Serial.println(gps.time.second()); // Second (0-59) (u8)
Serial.println(gps.satellites.value()); // Number of satellites in use (u32)
The first step should be that your GPS module gets the correct time. This should happen after a few minutes, probably. Then the number of satellites in use should go up, and you should start getting valid results once a reasonable number of satellites are found. I tend to get a reading with probably about 9 satellites.
If it is a cheaper module it might take a while, especially from a cold start.

Arduino Uno sim808 init error

Hey so I have arduino uno and a sim808 with gps antenna and gsm antenna. So here's the sample code:
#include <DFRobot_sim808.h>
#include <SoftwareSerial.h>
#define PIN_TX 3
#define PIN_RX 4
SoftwareSerial mySerial(PIN_TX,PIN_RX);
//DFRobot_SIM808 sim808(&mySerial);//Connect RX,TX,PWR,
DFRobot_SIM808 sim808(&mySerial);
void setup() {
//mySerial.begin(9600);
Serial.begin(9600);
//******** Initialize sim808 module *************
while(!sim808.init()) {
delay(1000);
Serial.print("Sim808 init error\r\n");
}
//************* Turn on the GPS power************
if( sim808.attachGPS())
Serial.println("Open the GPS power success");
else
Serial.println("Open the GPS power failure");
}
void loop() {
//************** Get GPS data *******************
if (sim808.getGPS()) {
Serial.print(sim808.GPSdata.year);
Serial.print("/");
Serial.print(sim808.GPSdata.month);
Serial.print("/");
Serial.print(sim808.GPSdata.day);
Serial.print(" ");
Serial.print(sim808.GPSdata.hour);
Serial.print(":");
Serial.print(sim808.GPSdata.minute);
Serial.print(":");
Serial.print(sim808.GPSdata.second);
Serial.print(":");
Serial.println(sim808.GPSdata.centisecond);
Serial.print("latitude :");
Serial.println(sim808.GPSdata.lat);
Serial.print("longitude :");
Serial.println(sim808.GPSdata.lon);
Serial.print("speed_kph :");
Serial.println(sim808.GPSdata.speed_kph);
Serial.print("heading :");
Serial.println(sim808.GPSdata.heading);
Serial.println();
//************* Turn off the GPS power ************
sim808.detachGPS();
}
}
So I'm always getting a result of "sim808 init error"
I don't know what the problem is but I do hope that the sim808 isn not broken because it has light in STA(status) and in NET(network) that is slowly blinking but there's no light in PPS(gps) I don't know what's the problem I'm really really confused.
//mySerial.begin(9600);
This line just below the void setup must be a code part not comment, delete the
'//'
mySerial.begin(9600);
Serial.begin(9600);
Also 6th line
//DFRobot_SIM808 sim808(&mySerial);//Connect RX,TX,PWR,
must be part of code not comment, delete the '//'
Try again as
DFRobot_SIM808 sim808(&mySerial);//Connect RX,TX,PWR,
It should work, since it is a cold start it might take time, if you had problem again correcting those comment lines into code, just swap the pins
You must use pins 7 and 8 of the Arduino as Tx and Rx. With the 3 and 2 you have selected it will not work for you.

nrf24l01 Transmission problems

I've been reading a lot of questions and answers regarding nrf24l01 and Arduinos while I was trying to figure out my problem. I'm fairly sure no one had this issue yet but I might be wrong. Here is my problem:
If I upload the sending code to the UNO and the receiving code to the NANO I keep getting errors. And nothing gets transmitted. However, if I do the opposite and I upload the sending code to the NANO and the receiving code to the UNO, everything is fine... I've been scratching my head for a couple days without any idea and I would like to get input from other people because I ran out of ideas...
I tried different nrf24l01 modules (I got about 20) to see if one was fried. Still the same thing. Tried changing to different pins... still the same thing. Changed the code to get it simpler and simpler to narrow down.. still the same thing. Maybe it requires more power to scan than send a package and the 3.3v from the Nano is not enough? I highly doubt..
I'm really curious if you guys can figure this one out. I think I provided a lot of info. If you need more feel free to ask.
Here is my set-up:
Arduino Nano:
And here is the log from the printDetails() function:
STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1 = 0xb01dfacece 0xb01dfacece
RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6
TX_ADDR = 0xb01dfacece
RX_PW_P0-6 = 0x20 0x20 0x00 0x00 0x00 0x00
EN_AA = 0x3f
EN_RXADDR = 0x02
RF_CH = 0x73
RF_SETUP = 0x07
CONFIG = 0x0e
DYNPD/FEATURE = 0x00 0x00
Data Rate = 1MBPS
Model = nRF24L01+
CRC Length = 16 bits
PA Power = PA_MAX
Arduino Uno:
STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1 = 0xb01dfacece 0xb01dfacece
RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6
TX_ADDR = 0xb01dfacece
RX_PW_P0-6 = 0x20 0x20 0x00 0x00 0x00 0x00
EN_AA = 0x3f
EN_RXADDR = 0x02
RF_CH = 0x73
RF_SETUP = 0x07
CONFIG = 0x0e
DYNPD/FEATURE = 0x00 0x00
Data Rate = 1MBPS
Model = nRF24L01+
CRC Length = 16 bits
PA Power = PA_MAX
Here is the Receiver code:
#include <SPI.h>
#include "RF24.h"
#include "nRF24L01.h"
#include "printf.h"
RF24 myRadio (7,8);
const uint64_t pipe = 0xB01DFACECEL;
struct package
{
int id=0;
int code = 0;
char text[100] = "";
};
typedef struct package Package;
Package data;
void setup() {
Serial.begin(115200);
printf_begin();
delay(1000);
myRadio.begin();
myRadio.setChannel(115);
myRadio.openReadingPipe(1,pipe);
myRadio.printDetails();
myRadio.startListening();
Serial.println("Set-Up Done");
delay(1000);
}
void loop() {
if(myRadio.available())
{
while(myRadio.available())
{
myRadio.read(&data, sizeof(data));
Serial.print("\nPackage");
Serial.println(data.id);
Serial.println(data.code);
Serial.println(data.text);
}
}
delay(500);
}
Here is the Sending code:
#include <SPI.h>
#include "RF24.h"
#include "nRF24L01.h"
#include "printf.h"
RF24 myRadio (7,8);
const uint64_t pipe = 0xB01DFACECEL;
struct package
{
int id=1;
int code = 2;
char text[100] = "text";
};
typedef struct package Package;
Package data;
void setup() {
Serial.begin(9600);
printf_begin();
delay(1000);
myRadio.begin();
myRadio.setChannel(115);
myRadio.openWritingPipe(pipe);
myRadio.setRetries(15,15);
myRadio.printDetails();
myRadio.stopListening();
Serial.println("Set-Up Done");
delay(1000);
}
void loop() {
if(!myRadio.write(&data, sizeof(data)))
{
Serial.println("error!!");
myRadio.printDetails();
}
Serial.print("\nPackage");
Serial.println(data.id);
Serial.println(data.code);
Serial.println(data.text);
data.id += 1;
data.code += 1;
delay(3000);
}
Try putting a 10uf capacitor across the +3.3v and gnd of each of the nRF24L01 module.
These modules need a lot of sending power which the capacitor helps with. I hope it works for you.
Try putting a 10uf capacitor across the +3.3v and gnd of each of the nRF24L01 module.
If that dosen't work, run the nrf24l01 off its own supply, 3.3v but have seen these peak at 1A! sending bursts. and the poor Nano's 3.3V comes from the FT232 chip, only 50mA is available.

Arduino send HEX values via XBee

I'm trying to send HEX values via XBee from a Arduino to digi's Xbee program XCTU. But i have some problems with some bytes that i cant send
The list of bytes i cant send:
0x11
0x13
0x7D
0x7E
0x81
0xEC
0xEE
If i use any other bytes i can see it in the XCTU console window and i get a response back to the Arduino
I have enabled API mode (AP=1) on both of the Xbee's. Im using the XBee lib linked from Arduino web site (https://www.arduino.cc/en/Reference/Libraries)
My code looks like this:
#define XBEE_RX_PIN 8
#define XBEE_TX_PIN 9
SoftwareSerial xbeeSerial(XBEE_RX_PIN, XBEE_TX_PIN);
void setup()
{
Serial.begin(9600);
xbeeSerial.begin(9600);
xbee.begin(xbeeSerial);
}
void loop()
{
Serial.println("Send next 255 msg:");
uint8_t testMsg[1] = { 0x0 };
for (uint8_t i = 0; i <= 0xFF; i++)
{
test2[0] = i;
Tx16Request testTx = Tx16Request(0xFFFF, testMsg, sizeof(testMsg));
xbee.send(testTx);
Serial.print("Message send: ");
Serial.println(test2[0], HEX);
if (xbee.readPacket(5000)) {
Serial.println("SUCCESS");
}
else if (xbee.getResponse().isError()) {
Serial.println("isError");
}
else {
Serial.println("No Response");
}
}
Serial.println("");
delay(3000);
}
With AP=1, you can't send some special bytes like:
0x7E (start of frame)
0x11/0x13 (XOn XOff)
...
As mentioned in the XBee documentation (XBee®XBee-PRO® ZB RF Modules manual 90000976_W.pdf, starting page 112), you should use AP=2 mode which allows you to transmit these special bytes by escaping them:
Escape characters.
When sending or receiving a UART data frame, specific data values must be
escaped (flagged) so they do not interfere with the data frame sequencing.
To escape an interfering data byte, insert 0x7D and follow it with the byte to be escaped XOR’d with 0x20.
Note that, if not escaped, 0x11 and 0x13 is sent as is.
Data bytes that need to be escaped:
- 0x7E – Frame Delimiter
- 0x7D – Escape
- 0x11 – XON
- 0x13 – XOFF
Example - Raw UART Data Frame (before escaping interfering bytes):
- 0x7E 0x00 0x02 0x23 0x11 0xCB
0x11 needs to be escaped which results in the following frame:
- 0x7E 0x00 0x02 0x23 0x7D 0x31 0xCB
Note In the above example, the length of the raw data (excluding the checksum) is 0x0002 and the checksum of the non-escaped data (excluding frame delimiter and length) is calculated as:
0xFF - (0x23 + 0x11) = (0xFF - 0x34) = 0xCB.
Hope this helps

NFC MIFARE Ultralight C authentication failure

I recently got the NFC shield v1.0 for my arduino Uno board. I tried some of the starter code provided from seed's studio wiki http://www.seeedstudio.com/wiki/index.php?title=NFC_Shield. After multiple attempt at reading or writing a set of Mifare Ultralight C's, I set to try line by line to see what the issue was. I narrowed it down to more or less this line:
nfc.authenticateBlock( 1 /*1 or 2*/,
id /*Card NUID*/,
10/*0 to 63*/,
KEY_A /*Either KEY_A or KEY_B */,
keys))
The id for the card is correct, so i'm assuming another of the argument must be tripping things up. I'm using keys[]= {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} for the key. Anything else that might be the issue? I included my entire code below. Please let me know if you need additional details.
Thank you!
#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);
Serial.println();
uint8_t keys[]= {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; // default key of a fresh card
if(nfc.authenticateBlock( 1 /*1 or 2*/,
id /*Card NUID*/,
0x08 /*0 to 63*/,
KEY_A /*Either KEY_A or KEY_B */,
keys))
{
Serial.println("authenticated!");
}
else {
Serial.println("failed to authenticate");
}
}
delay(2000);
}
You are using the MIFARE Classic authentication function for authenticatication with a MIFARE Ultralight C chip. As the two kinds of chips use entirely different methods of authentication, this will not work.
You don't need to authenticate a write/read of an ultralight NFC tag. I was having the same problems.
The problem with the library from seedstudio or any other place is that they only support reading the ultralight tags.
I tried to "force" the write to the tag, with no success, because the function doesn't exist in the library. You write to sectors/blocks on a Classic Mifare, but you need to write to Pages in the ultralight tag. You need to MAKE the function within NFC.H/NFC.PP so that you can write to the ultralight pages.
Check how the structure of a NFC Ultralight tag is, smaller blocks in each page
http://www.sonmicro.com/en/downloads/Mifare/um_sm130_a2.pdf

Resources