I am beginning to work with XBee RF Modules and have a general concern as to how and why this timing issue occurs... The two XBee do indeed communicate, and I am testing one thru Shield on Arduino Uno and the other via USB Connector on PC and X-CTU. The code is (generally) as follows, using the sample code from Sparkfun as a base (located at https://learn.sparkfun.com/tutorials/xbee-shield-hookup-guide)
// We'll use SoftwareSerial to communicate with the XBee:
#include <SoftwareSerial.h>
// XBee's DOUT (TX) is connected to pin 2 (Arduino's Software RX)
// XBee's DIN (RX) is connected to pin 3 (Arduino's Software TX)
SoftwareSerial XBee(2, 3); // RX, TX
void setup()
{
// Set up both ports at 9600 baud. This value is most important
// for the XBee. Make sure the baud rate matches the config
// setting of your XBee.
XBee.begin(9600);
Serial.begin(9600);
}
void loop()
{
if (XBee.available())
{ // If data comes in from XBee, send it out to serial monitor
Xbee.write("ready");
Serial.write(XBee.read());
}
}
My concern comes with the fact I am sending packets of 2 ASCII chars (2 digits, 10, 20, 30, etc) just to test. In the console monitor of X-CTU, I notice the following. (bold being received, italic being sent.)
10 readyready 20 readyready 30 readyready etc...
Can someone explain to me in layman's terms of how this is occurring? I cannot understand how the code executes in this order.
You're using "AT mode" or "transparent serial" mode on your XBee, so characters arrive one at a time. There isn't any packetizing going on.
So you send a packet with 10 from X-CTU. The XBee on your Arduino receives that packet and starts sending the payload to the Arduino. The Arduino receives 1 which triggers the code to send ready in response. Then the Arduino receives 0 and sends another ready.
You would need to add some sort of framing to your serial stream (like adding a carriage return after each line of data) or switch to API mode (which delivers network payloads wrapped in headers and a checksum) if you want to look at your data in chunks, instead of as a stream.
I haven't used it, but there's an xbee-arduino library designed for using XBee modules in API mode on Arduino microcontrollers.
Related
As an introduction, I bought myself an arduino and a few modules to learn some software stuff. The project is to eventually connect to a bluetooth OBD2 reader on my car to display real time data on a small LCD.
The problem
I am either not able to connect to, or not write to, my HC05 module via software serial. I think I have narrowed this down to a couple possibilities.
I am unable to connect to the module in the first place.
I have a Mega 2560 and HC05.
5V <-> VCC
GND <-> GND
D2 <-> RXD
D3 <-> TXD
Note that I have seen 9600 and 38400 baud rates for connecting but neither worked, so I made this function to try them all for me...
//set up serial relay into HC05.
SoftwareSerial hc05(2,3);
//computer serial baud rate 115200
bool hc05_connect() {
long baud_list[] = {300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 74880, 115200, 230400};
Serial.println("Attempting to connect to HC05 bluetooth module...");
bool success = 0;
for (int i=0; i<(sizeof(baud_list) / sizeof(baud_list[0])); i++) {
Serial.print("Baud rate ");
Serial.print(baud_list[i]);
Serial.print("...");
hc05.begin(baud_list[i]);
hc05.write("AT");
delay(1000);
if (hc05.available()) {
Serial.println(" successful!");
success = 1;
return success;
} else {
Serial.println(" failed");
}
}
return success;
}
Notes:
This has always returned failed for every baud rate.
I have the bluetooth module in command mode, initiated by pressing the button as I supply power.
I have tried unplugging the TX/RX pins while uploading the sketch. No difference noted.
My attempts to send commands to the HC05 are failing.
Below is my function for sending commands to the module.
void loop() {
// listen for communication from the ESP8266 and then write it to the serial monitor
if (hc05.available()) {
Serial.write(hc05.read());
}
// listen for user input and send it to the ESP8266
if (Serial.available() > 0) {
Serial.println("Writing to hc05...");
Serial.println(Serial.available());
Serial.println(Serial.read());
hc05.write(Serial.read());
}
}
I have added in a few lines which write back to Serial so I can see what's being sent, and the monitor returns weird stuff. For example, if I send "AT", this is what the monitor reads:
Writing to hc05...
3
65
Writing to hc05...
1
10
Notes:
Why is it sending 2 different items?
Why is it sending integers rather than the characters I said?
Does this indicate I'm just sending it nonsense commands so it's not responding?
I can provide full code if you want, this is already a huge textwall though. Please help me!
Edit
So I have been able to get communication two ways via the bluetooth module using a modified version of the code in this instructable: https://www.instructables.com/How-to-Set-Up-and-Test-Arduino-Bluetooth-Connectio/
I was able to send from PC only and not receive to an android bluetooth terminal using SoftwareSerial with HC05's RX - TX0 / TX - RX0.
And I was able to receive to PC and not send using hardware serial / Serial1 with HC05's RX - TX1 / TX - RX1.
So now I have RX - TX0 / TX - RX1. It seems to communicate through terminal like this.
void setup() {
Serial.begin(9600); //open the serial port
Serial1.begin(9600);
}
void loop() {
if (Serial1.available()) {
Serial.print("(Received)");
Serial.println(Serial1.readString()); // send from serial to bluetooth
}
if (Serial.available()) {
Serial.print("(Sent)");
Serial.println(Serial.readString());
Serial1.println(Serial.readString()); // send from bluetooth to serial
}
}
But if I apply this to my code, I still can't get it to work.
Before I try to hack this together, why am I getting serial to work across 2 different serial channels? Weird...
Okay, so I figured it out. (I can't say I fully understand, but maybe this will help people in future.)
1. Unable to connect to module
Thanks #ukBaz for suggesting I connect with the terminal app on my phone, this allowed me to debug the connection to the module in the first place. and #Juraj for suggesting that the Mega uses hardware serial.
Serial1 apparently is broken on my board, so I am using Serial3. I bluetoothed to the device with my phone, and was able to send commands back and forth between Serial and Serial3 both on 9600 baud rate. Here is the code I used:
void setup() {
Serial.begin(9600); //open the serial port to PC
Serial3.begin(9600); //open serial port to HC05. TX -> 15, RX -> 14
}
void loop() {
if(Serial3.available()){
Serial.print(Serial3.readString()); // send from serial to bluetooth
}
if(Serial.available()){
Serial3.print(Serial.readString()); // send from bluetooth to serial
}
}
I suspect I was using the wrong read/readString and write/print/println for my purpose initially.
2. Unable to issue commands to the module
Once I got that working, I changed the baud rate to 38400, and tied the STATE pin of the module to VCC (rather than using the button). Uploaded code, disconnected 5V, reconnected 5V, reset arduino.
At that point, I could issue "AT" to the module via Serial Monitor, and receive "OK" back. Woohoo!
I think I understand now that #hlovdal was suggesting that I was issuing a command to the module and never parsing a response I got, so it was.. clogged parhaps? In any case. I can now successfully issue commands and receive responses from the module.
Thanks everyone for your help.
There are some problems with how you are communicating AT command lines to your device. For instance:
hc05.write("AT");
delay(1000);
You do not send an AT command to a modem, you send an AT command line that contains zero or more AT commands, followed by a command line terminating character (that always should be '\r', aka carriage return (or <CR>)).
You are missing that terminating character here, so the modem will never send you a reply, because you have not sent it a command line.
And also, you should never, ever use delay as a substitute for reading and parsing the responses that the modem sends back. See this answer for some more details.
I have a SIM800L module.
I have configured my 800L SIM module, where I connect OUT+ on LM2596 to VCC on SIM800L and OUT- on LM2596 to GND on SIM800L. Besides that, I connect TX SIM800L to pin 2 Arduino and RX SIM800L to pin 3 Arduino
Then, After the source code is uploaded to the arduino mega 2560 board, the SIM800L module flashes 3 times every 3 seconds, sometimes also blinks 7 times every 3 seconds. So on.
And until now my SIM800L module cannot send messages. where is the problem? thanks please answered
First, you must double check that the modem is connected correctly and have enough power. To ensure that I always try to read the output serial of the modem in startup and make a call to it.
If modem starts correctly it should print some data in the serial output (with default settings) and some of them prints the power issues.
You can use the following example to creating a two-way communication between your host PC and the modem. In here I'm using Serial1 with pins 18, 19.
If I remember correctly the blinks should be every 3 seconds, and if it changes it means that modem is being restarted.
After that, you can send AT commands with your host PC and check the functions.
#include <SoftwareSerial.h>
#define serialSIM800 Serial1
void setup()
{
//Begin serial communication with Arduino and Arduino IDE (Serial Monitor)
Serial.begin(9600);
//wait on host serial
while (!Serial);
//Being serial communication with Arduino and SIM800
// you should double check the default baudrate of SIM800 and set it here
serialSIM800.begin(9600);
delay(1000);
Serial.println(“Setup Complete !”);
}
void loop()
{
//Read SIM800 output (if available) and print it in Arduino IDE Serial Monitor
if (serialSIM800.available())
{
Serial.write(serialSIM800.read());
}
//Read Arduino IDE Serial Monitor inputs (if available) and send them to SIM800
if (Serial.available())
{
serialSIM800.write(Serial.read());
}
}
I have a Bluetooth module connected to my RX(0) pin on the Arduino through which I am receiving data.
I am then printing that data using a Serial.write().
These two pins correspond to COM16 in my computer.
I am now able to receive these values into processing and print them again in processing after I set the COM port to 16 in processing.
Now I want to send a particular value out from processing back to Arduino again via serial communication. I figured I could do this with the software serial.
However, I have a few questions as to how the software serial works:
If I setup a software serial, what is the COM port for the software serial for which I can send values out from processing to the Arduino?
This is the command to set the COM port in processing.
String portName ="COM16";
myPort = new Serial(this, portName, 57600);
I then use myPort.write() to send some values back to the Arduino but how do I capture the values in the soft serial?
The best way is to use Serial Event
Minimal code:
void setup() {
Serial.begin(9600); // initialize serial
}
void loop() { // you need to define a loop function even
// if not used at all.
}
// This is an interrupt.
// Code below will only execute when something is received in the RX pin.
void serialEvent() {
while (Serial.available()) {
char inChar = (char)Serial.read(); // get the new byte
// here you can process the received byte
}
}
If you want to receive several bytes before processing them check the example in the link provided, where it concatenates the chars into a string until the \n byte is received
The advantage of this approach is that it uses interruptions, so you don't need to constantly check if something is received in the serial port.
PD: I see that in your code you use a baudrate of 57600. Just modify the code above to make sure you use the same speed, otherwise you will not receive anything (or even worse, you will receive garbage)
I would do it the other way around: use SoftSerial / AltSoftSerial for the Bluetooth module comms and the Hardware Serial for comms with Processing.
Bare in mind SoftSerial may not be as robust as a proper hardware serial port.Baud rate 57600 should work, but bare in mind higher baud rates may be unreliable.
Alternatively, if the budget/time allows it, you could use an Arduino that has multiple Serial ports (such Arduino Mega, Due, etc. which have Serial, Serial1, etc.)
I recently bought an Arduino UNO to read the data outputted by my Smart Meter. The meter uses serial communication and I would like to see the values being outputted on my laptop screen. I figured I would need to use the SoftwareSerial library to read the incoming data and print that data on my screen using the hardware serial and the Serial Monitor in the Arduino IDE. To become familiar with (software) serial communication on the Arduino, I reviewed the documentation of the SoftwareSerial library. Problem is, I can't get the most basic example to work and I have been stuck on this for quite a while now. The example code is below, the example can be found here
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(57600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.println("Goodnight moon!");
// set the data rate for the SoftwareSerial port
mySerial.begin(4800);
mySerial.println("Hello, world?");
}
void loop() { // run over and over
if (mySerial.available()) {
Serial.write(mySerial.read());
}
if (Serial.available()) {
mySerial.write(Serial.read());
}
}
As far as I understand this, the following should happen:
- Type text in Serial Monitor window.
- Serial.read() reads this data and writes it to the Software Serial.
- The Software Serial reads this data and writes it back to Serial.
- That which was written appears on the screen.
But whatever I try, nothing happens. Among things I tried to following:
- Change the baud rate for both software and hardware serial (9600 for instance).
- Tried a different SoftwareSerial library (AltSoftSerial).
- Tried different RX and TX pins for SoftwareSerial.
- Instead of Serial.write(mySerial.read());, store the result in a char first.
I'm probably missing something obvious. I would be grateful to anyone who could shed some light on this or offer an alternative way for me to read the data from my Smart Meter.
Edit
I had no wiring, because the example specified "There is no circuit for this example". I tried all three options suggested by #slash-dev, but none had the expected behaviour:
SoftwareSerial with wires connecting pin 1 to pin 10 and pin 0 to pin 11. It prints strange characters:
Goodnight moon!
Ùniÿhtÿmoÿn!ÿ
nihtmoÿttt
AltSoftSerial with wires connecting 1-8 and 0-9. First prints Goodnight moon! and then it keeps printing Ô당¥�¡Ñ�moon!.
NeoSWSerial with wires connecting 1-10 and 0-11. Same as AltSoftSerial but keeps printing Ôë‹–+ë¡Ñ�j½½¹…j.
The baud rates must be the same on Serial and mySerial.
And you don't describe the connections, so I have to ask: Did you connect a wire from pin 1 (Serial transmit) to pin 10 (mySerial receive), and another wire from pin 0 (Serial receive) to pin 11 (mySerial transmit)? Note how they are crossed.
AltSoftSerial is really the best choice, but it only works on pin 8 (RX) and pin 9 (TX), which would require connecting 8 to 1 and 9 to 0. SoftwareSerial is very inefficient, because it disables interrupts for long periods of time. This can interfere with other parts of your sketch or other libraries.
My NeoSWSerial library is another alternative. It's almost as efficient as AltSoftSerial, but it works on any two pins. It can transmit and receive at the same time (unlike SoftwareSerial), but it only works at bauds 9600, 19200 and 38400.
EDIT:
I think what you've tried is probably working ok. All the software serial libraries use interrupts for processing individual bits instead of one interrupt per character. When there are other interrupts in the system (millis() TIMER0 or Serial), the bit "calculations" can be affected. This manifests as receiving the wrong byte. Your loopback test makes it especially susceptible because the sending and receiving are synchronized (the initial receive interrupt occurs while the transmit interrupt is starting the next char).
If you just hook 0 to 1, I think it will work, because the UART is able to send and receive at the same time, and it deals with complete characters, not bits. The character interrupts do not disturb the sending or receiving of the bits.
In developing the NeoSWSerial library, I have seen this manifest the same way. I had to use two Arduinos to fully test asynchronously (i.e., not synchronized). In your case, using AltSoftSerial for the SmartMeter should work fine, and you can choose different baud rates. If you are echoing the SmartMeter characters to Serial, be sure you have a higher baud rate on Serial.
This is most likely not related to the issues now 5 years ago, but in my case I was using the Arduino IDE 2.0.0-rc5 which was not writing to the soft serial for unknown reasons. I downgraded to Arduino IDE 1.8.19 and the same serial sketch worked.
I want to send some commands to my RN41 Bluetooth Module connecting to Arduino Leonardo over the serial port using serial monitor, as the tutorial shows. But it does not respond. I can connect to the bluetooth modul and the status LED blinks right. I tried to send $$$ to change to command mode, and the blink rate does change to 10/sec, but module responds nothing. And when I send '---', the blink rate back to normal. I think it means the connection is successful but I just cannot see anything at serial monitor.
I set monitor's baud to 9600, as exactly the tutorial shows. (https://learn.sparkfun.com/tutorials/using-the-bluesmirf/example-code-using-command-mode)
Do you guys know what could be wrong?
Code attached:
/*
Example Bluetooth Serial Passthrough Sketch
by: Jim Lindblom
SparkFun Electronics
date: February 26, 2013
license: Public domain
This example sketch converts an RN-42 bluetooth module to
communicate at 9600 bps (from 115200), and passes any serial
data between Serial Monitor and bluetooth module.
*/
#include <SoftwareSerial.h>
int bluetoothTx = 2; // TX-O pin of bluetooth mate, Arduino D2
int bluetoothRx = 3; // RX-I pin of bluetooth mate, Arduino D3
SoftwareSerial bluetooth(bluetoothTx, bluetoothRx);
void setup()
{
Serial.begin(9600); // Begin the serial monitor at 9600bps
bluetooth.begin(115200); // The Bluetooth Mate defaults to 115200bps
bluetooth.print("$"); // Print three times individually
bluetooth.print("$");
bluetooth.print("$"); // Enter command mode
delay(100); // Short delay, wait for the Mate to send back CMD
bluetooth.println("U,9600,N"); // Temporarily Change the baudrate to 9600, no parity
// 115200 can be too fast at times for NewSoftSerial to relay the data reliably
bluetooth.begin(9600); // Start bluetooth serial at 9600
}
void loop()
{
if(bluetooth.available()) // If the bluetooth sent any characters
{
// Send any characters the bluetooth prints to the serial monitor
Serial.print((char)bluetooth.read());
}
if(Serial.available()) // If stuff was typed in the serial monitor
{
// Send any characters the Serial monitor prints to the bluetooth
bluetooth.print((char)Serial.read());
}
// and loop forever and ever!
}
I was stuck on very simple case:
To enter command mode you have to send $$$ without any CR/LF.
after you entered command mode you have to send commands, and every command has to be followed by CR LF. if not - module will not response.
Hope that helps.
Yes, send only 3 characters, "$$$". I was also stuck for a bit. I also found that reading the Mate response "CMD" is necessary, which is not shown in the published sketch.
I've got some brandnew RN41VX modules.
I connect them by a XBEE Explorer USB module (almost same as RN41 EVAL Kit) to computer.
Using a terminal with 115 kbaud I send $$$ (without any trailing chars as 0x0d) to get into command mode. The LED switches to 10Hz blinhking - all fine.
But no respone appears in terminal.
Solution:
I had to switch on RTS Signal, even if manual tells "Flow Control: none"
kind regards Volker