I am working on a project in which I use a phone app that I built in order to use Google's Speech Recognizer, connect my phone with my Arduino via Bluetooth and then when I say a word it sends the word in order to display it in a LCD.
The phone App works great with no problems. The problem is in the Arduino code. When I say the word hello for example the Arduino receives ello. I know that it receives it because I also use the Serial monitor to display the data in my computer screen except the LCD. Then after Arduino receives the first chunk of data if I send a second word like world Arduino receives elloorld. So it not only misses again the first letter of the word but also the Serial Port is not empty it in the end of the loop.
I tried with data += c; instead of data.concat(c); and the difference is that the second word isn't elloorld and it is just orld
Here is my code:
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 9, 8, 7, 6, 5, 4, 3, 2);
char c;
String data = "";
void setup() {
lcd.begin(16, 2);
Serial.begin(9600);
}
void loop() {
lcd.clear(); //clean the lcd
lcd.home(); // set the cursor in the up left corner
while(Serial.available() > 0){
c = Serial.read();
data.concat(c);
}
if(data.length() > 0){
Serial.println(data);
}
lcd.print(data);
delay(3000);
data = "";
}
If in the end of the loop I try to clean the Serial Port with this code:
while(Serial.available() > 0){
Serial.read();
}
Then the arduino doesn't receive data at all.
Your code wakes up every 3000 ms, then processes everything that is pending in the Serial input buffer and falls asleep again.
If you remove that ugly String data and the ugly delay(3000) and the unnecessary while, you can try this simple loop:
unsigned long lastreceived;
void loop() {
if (Serial.available()) {
lcd.write(Serial.read());
lastreceived=millis();
}
if (millis() - lastreceived > 1000) {
// after one second of silence, prepare for a new message
lcd.clear();
lcd.home();
lastreceived=millis(); // don't clear too often
}
}
Related
I am doing a project where I need to send data from ultrasonic sensor wirelessly present in one arduino to other arduino where I need these values in Serial monitor. But the problem is I cannot able to send these values through bluetooth. I tried to send one character, it is appearing in serial monitor.. But when I tried to the same for integer values it is not appearing in serial monitor.
I have configured Master and Slave modes for the Bluetooth. I have uploaded the image of the code which I am using to send these values. Please help me on this. Thanks in advance .
code
//# transmitting end
#define trigPin 12
#define echoPin 11
void setup() {
Serial.begin(38400); // Default communication rate of the Bluetooth module
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}
void loop() {
long duration;
float distance;
digitalWrite(trigPin, LOW); // Added this line
delayMicroseconds(2); // Added this line
digitalWrite(trigPin, HIGH);
delayMicroseconds(10); // Added this line
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance = (duration/2) / 29.1;
Serial.println(distance,2); // Sends floatValue
delay(500);
}
//# receving end
#include <SoftwareSerial.h>
#define led 13
SoftwareSerial BTSerial(10, 11);
int data=0;
void setup() {
pinMode(led,OUTPUT);
Serial.begin(38400);
BTSerial.begin(38400); // Default communication rate of the Bluetooth module
}
void loop() {
int number;
if(Serial.available() > 0){ // Checks data is from the serial port
data = BTSerial.read(); // Reads the data from the serial port
//analogWrite(led,data);
delay(10);
//Serial.println(data);
}
Serial.println(data);
}
I need integer values at the serial monitor. But there I am getting some symbols like ?/<>..
From the Arduino reference, Serial.read() only reads the first available byte available in the Serial buffer. As an int is coded on 8 bytes, I would say that you need to read the incoming bytes sequentially in order to get the full value.
Maybe you can implement this by putting (Serial.available() > 0) in a while loop, concatenate the values you get in a char[8] for instance and then convert this char to a integer value.
Also, beware that you are sending floats and not int.
Thanks for the help..!
I modified the code in the receiver end to get the float values from the transmitter.. Here is my modified code
#include <SoftwareSerial.h>
int bluetoothTx = 10;
int bluetoothRx = 11;
String content; //content buffer to concatenate characters
char character; //To store single character
SoftwareSerial bluetooth(bluetoothTx, bluetoothRx);
void setup(){
bluetooth.begin(38400);
Serial.begin(9600);
}
void loop(){
bluetooth();
}
void bluetooth(){ //
while(bluetooth.available()){
character = bluetooth.read();
content.concat(character);
if(character == '\r'){ // find if there is carriage return
Serial.print(content); //display content (Use baud rate 9600)
content = ""; //clear buffer
Serial.println();
}
}
}
I am using ESP8266 and ModbusMaster.h library to communicate with RS485 enabled power meter. Communication works fine but responses are the ones are confusing me and I can not get correct values. My power meter shows 1.49 kWh but response from Modbus is 16318. Here is my code:
#include <ArduinoOTA.h>
#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h>
#include <ModbusMaster.h>
#include <ESP8266WiFi.h>
/*
Debug. Change to 0 when you are finished debugging.
*/
const int debug = 1;
#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
int timerTask1, timerTask2, timerTask3;
float battBhargeCurrent, bvoltage, ctemp, btemp, bremaining, lpower, lcurrent, pvvoltage, pvcurrent, pvpower;
float stats_today_pv_volt_min, stats_today_pv_volt_max;
uint8_t result;
// this is to check if we can write since rs485 is half duplex
bool rs485DataReceived = true;
float data[100];
ModbusMaster node;
SimpleTimer timer;
// tracer requires no handshaking
void preTransmission() {}
void postTransmission() {}
// a list of the regisities to query in order
typedef void (*RegistryList[])();
RegistryList Registries = {
AddressRegistry_0001 // samo potrosnju
};
// keep log of where we are
uint8_t currentRegistryNumber = 0;
// function to switch to next registry
void nextRegistryNumber() {
currentRegistryNumber = (currentRegistryNumber + 1) % ARRAY_SIZE( Registries);
}
void setup()
{
// Serial.begin(115200);
Serial.begin(9600, SERIAL_8E1); //, SERIAL_8E1
// Modbus slave ID 1
node.begin(1, Serial);
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
// WiFi.mode(WIFI_STA);
while (Blynk.connect() == false) {}
ArduinoOTA.setHostname(OTA_HOSTNAME);
ArduinoOTA.begin();
timerTask1 = timer.setInterval(9000, updateBlynk);
timerTask2 = timer.setInterval(9000, doRegistryNumber);
timerTask3 = timer.setInterval(9000, nextRegistryNumber);
}
// --------------------------------------------------------------------------------
void doRegistryNumber() {
Registries[currentRegistryNumber]();
}
void AddressRegistry_0001() {
uint8_t j;
uint16_t dataval[2];
result = node.readHoldingRegisters(0x00, 2);
if (result == node.ku8MBSuccess)
{
for (j = 0; j < 2; j++) // set to 0,1 for two
datablocks
{
dataval[j] = node.getResponseBuffer(j);
}
terminal.println("---------- Show power---------");
terminal.println("kWh: ");
terminal.println(dataval[0]);
terminal.println("crc: ");
terminal.println(dataval[1]);
terminal.println("-----------------------");
terminal.flush();
node.clearResponseBuffer();
node.clearTransmitBuffer();
} else {
rs485DataReceived = false;
}
}
void loop()
{
Blynk.run();
// ArduinoOTA.handle();
timer.run();
}
I have tried similar thing but with Raspberry Pi and USB-RS485 and it works.
Sample of NodeJS code is below. It looks similar to Arduino code.
// create an empty modbus client
var ModbusRTU = require("modbus-serial");
var client = new ModbusRTU();
// open connection to a serial port
client.connectRTUBuffered("/dev/ttyUSB0", { baudRate: 9600, parity: 'even' }, read);
function write() {
client.setID(1);
// write the values 0, 0xffff to registers starting at address 5
// on device number 1.
client.writeRegisters(5, [0 , 0xffff])
.then(read);
}
function read() {
// read the 2 registers starting at address 5
// on device number 1.
console.log("Ocitavanje registra 0000: ");
client.readHoldingRegisters(0000, 12)
.then(function(d) {
var floatA = d.buffer.readFloatBE(0);
// var floatB = d.buffer.readFloatBE(4);
// var floatC = d.buffer.readFloatBE(8);
// console.log("Receive:", floatA, floatB, floatC); })
console.log("Potrosnja u kWh: ", floatA); })
.catch(function(e) {
console.log(e.message); })
.then(close);
}
function close() {
client.close();
}
This code displays 1.493748298302 in console.
How can I implement this var floatA = d.buffer.readFloatBE(0); in Arduino? Looks like that readFloatBE(0) does the trick, but available only in NodeJS / javascript.
Here i part of datasheet for my device
Here is what I am getting as result from original software that came with device:
If someone could point me in better direction I would be thenkfull.
UPDATE:
I found ShortBus Modbus Scanner software and tested readings.
Library read result as Unsigned integer, but need Floating Point and Word Order swapped. It is shown on image below.
Can someone tell how to set proper conversion please.
Right, so indeed the issue is with the part done by var floatA = d.buffer.readFloatBE(0);Modbus returns an array of bytes, and the client has to interpret those bytes, ideally done by the library you're using, but if not available on Arduino, you may try manually with byte decoding functions, with the following considerattions:
Modbus registers are 16 bit in length, so length 1 = 16 bits, length
2 = 32 bits, hence the data type noted on the docs as float32 means
"2 registers used for this value, interpret as float".
Therefore, on client.readHoldingRegisters(0000, 12)you're asking to read the register with address 00, and size 12... so this makes no sense, you only need 2 registers.
On your sample Node code, first you're writing
2 registers to address 5 in client.writeRegisters(5, [0 , 0xffff])
register 5 = 0, and register 6 = 0xFFFF, why? Then you go and read
from address 0, in read(), which is the address for Total KwH per
your docs.
So, you should get an array of bytes, and you need to
decode them as a float. Modbus is Big Endian for words and bytes, so
you need to use those in the decoding functions. I don't know exactly
what is available in Arduino, but hopefully you can figure it out
with this extra info.
I suppose that if you just send the buffer to print, you'll get an integer interpretation of the value, hence the problem
platform:Arduino UNO, Arduino Mega2560, HC-05
Here shows the detail.
In Arduino UNO(Master), I encode
Serial.print("A 1 2 3 4 5;");
In Arduino Mega2560(slave), I encode
void setup()
{
//connect to the PC
Serial.begin(9600);
//connect to the Arduino UNO(By bluetooth)
Serial1.begin(38400);
}
void loop()
{
//its value > 0
Serial.println(Serial1.available());
//output : 128 or 248
Serial.print(Serial1.read());
delay(1000);
}
The value of Serial.available() > 0 is true,
but the print result of Serial.print(Serial1.read()); is abnormal. it print
I want to know the reason and its solution.Thanks!
I'm assuming that you made sure that both the Bluetooth devices are connected properly and the baud rates are matched.
Now, one problem might be the buffer might be full. On the sender's side, provide a delay equal to or slightly higher than the delay on the receiver's side.
Next, on the receiver side, change void loop to this:
void loop(){
if(Serial1.avaialable() > 0){
char value = Serial1.read();
Serial.println(value);
delay(1000);
}
}
I manage to send data from NodeJs runtime with serialport library.
The goal is storing a string received from Serial.read() in Arduino . What is correct:
int string = Serial.read()
or:
char string[20] = Serial.read()
There are many documentations on Internet and they are not the same
P/s: I send string from nodejs in buffer form but i dont think it matters because arduino still implement it as a string anyway.
From the Arduino documentation:
int incomingByte = 0; // for incoming serial data
void setup() {
Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
}
void loop() {
// send data only when you receive data:
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
// say what you got:
Serial.print("I received: ");
Serial.println(incomingByte, DEC);
}
}
https://www.arduino.cc/en/Serial/Read
.read():
Returns the first byte of incoming serial data available (or -1 if no
data is available) - int
FYI: I've used this code many times and it works on 100%.
I'm trying to get my Raspberry Pi/Node.js to communicate with an Arduino Uno using node-serialport. I'm having trouble with the following block of code:
Raspberry Pi
var SerialPort = require("serialport").SerialPort;
var serialPort = new SerialPort("/dev/ttyACM0", {
baudrate: 9600
});
serialPort.on("open", function () {
console.log('open');
serialPort.on('data', function(data) {
console.log('data received: ' + data);
});
serialPort.write(new Buffer('4','ascii'), function(err, results) {
console.log('err ' + err);
console.log('results ' + results);
});
});
Arduino
// LED on pin 12
int led = 12;
// Incoming serial data
int data=0;
void setup() {
// Pin 12 set to OUTPUT
pinMode(led, OUTPUT);
// Start listening on the serialport
Serial.begin(9600);
}
void loop() {
if(Serial.available()>0){
// Read from serialport
data = Serial.read();
// Check and see if data received == 4
if(data=='4') {
// Blink the LED 3 times
for(int i=0;i<3;i++){
digitalWrite(led, HIGH);
delay(1000);
digitalWrite(led,LOW);
delay(1000);
}
// Reset data to 0
data=0;
}
}
}
I am only able to get the Arduino to blink the LED if I wrap a for loop around the serialPort.write() function. At the 40th loop iteration or so the LED finally starts blinking and will continue blinking until serialPort.write() loop is finished. This leads me to believe that I'm encountering some sort of timing issue. I'm looking for a more elegent (and non-blocking) solution to blinking the LED on the Arduino via the Pi. Any help would be greatly appreciated.
Thanks!
Bobby
The problem had to do with Arduino's "AutoReset" see more here.
I didn't actually disable autoreset... I went ahead and implemented the code I posted above. I require user interaction to trigger SerialPort.write(). This works as long as there is a few seconds between when the serial connection is opened and the first write.
My guess is that new Buffer('4','ascii') is doing an ASCII string, and not an ASCII character. The difference being that you're not sending 4, or 44444444… using your loop but 4\0 or 4\04\04\04\04\04\04\0… using your loop.
So when you do Serial.available(), it returns 2, as it got two byte buffered, but you only read one byte. As the buffer of the Arduino is a circular buffer that gets overwritten with new data over time, what can happen is that you're only reading the \0s, until over time the timings shift and you get to read only the 4s.
My advice would be to either read as many characters as there is in the buffer, or simply discard invalid reads, as Serial.read() return -1 when the buffer is empty:
const int led=12;
void setup() {
pinMode(led, OUTPUT);
Serial.begin(9600);
}
void loop() {
// Read from serialport
int data = Serial.read();
// Check and see if data received == 4
// and thus discard data==-1 or data==`\0`
if(data=='4') {
// Blink the LED 3 times
for(int i=0;i<3;i++){
digitalWrite(led, HIGH);
delay(1000);
digitalWrite(led,LOW);
delay(1000);
}
}
}