I have a project and this project depends entirely on the communication between Arduino Due and Nano 33 BLE.
I want to send data via UART from the sensor located in the Nano as float data, and I receive it in the form of a float as well.
But by using Serial.read(), the data will be send as int, and by using Parsefloat, the information is received incorrectly.
Is there a way to send sensor data from nano to Due without error? And in the right form?
Here is the Nano code:
float h = 22.5;
float x, y, z;
int i = 0;
unsigned long previousMillis = 0;
const long interval = 500;
void TimerOhne();
void Acceleration();
void setup()
{
Serial.begin(9600);
Serial1.begin(9600);
if (!IMU.begin())
{
Serial.println("Failed to initialize IMU!");
while (1)
;
}
Serial.println("Read the serial");
}
void loop()
{
// TimerOhne();
Acceleration();
}
void TimerOhne()
{
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval)
{
// save the last time you blinked the LED
previousMillis = currentMillis;
Serial1.write(h);
Serial.println(h);
Serial.println();
Serial.print("i ist: ");
Serial.print(i);
Serial1.write(66);
Serial1.write(i);
Serial.println();
i++;
}
}
void Acceleration()
{
if (IMU.accelerationAvailable())
{
IMU.readAcceleration(x, y, z);
}
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval)
{
x = x * 100;
y = y * 100;
Serial1.write(4);
Serial1.write(x);
Serial1.write(6);
Serial1.write(y);
Serial1.write(8);
Serial1.write(i);
i++;
Serial.print("X ist: ");
Serial.println(x);
Serial.print("y ist: ");
Serial.println(y);
}
}
Here is the Due code
float r;
unsigned long previousMillis = 0;
const long interval = 500;
void setup()
{
// Begin the Serial at 9600 Baud
Serial.begin(9600);
Serial1.begin(9600);
}
void loop()
{
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval)
{
previousMillis = currentMillis;
r = Serial1.read();
Serial.println(r);
}
}
To transport an float in binary you have to send the bytes of the float as a byte array.
Serial1.write((const uint8_t*) &x, sizeof(x));
you can receive them as
if (Serial1.available()) {
Serial1.readBytes((uint8_t*) &x, sizeof(x));
...
}
Note: this assumes the float type is encoded the same way on both sides, which is true since both MCU are ARM architecture.
If you want to transport the number as text and parse it on the other Arduino, use Serial1.print(x) to send it and you can use the parseFloat() function.
if (Serial1.available()) {
x = Serial1.parseFloat();
...
}
Related
I bought the same boards used in this video on Youtube (the componts are THIS geiger counter (that I am pretty sure its working, the tiks on the speacker are coerent) and THIS esp (I don't know if is here the problem or in the code), I loaded the arduino code into the esp32 board, but the display remains stuck on "Measuring". It connects correctly to the ThingSpeak channel, but always linearly increasing measurements. The number grows continuously (view the attached image). I tried to insert some currentMillis and previousMillis println. Both variables are always 0 in the serial monitor.
So I tried adding currentMillis = millis (); at the beginning of the loop (), at this point the display has finally shown "radioactivity" with the usual increasing numbers. Even if the card is disconnected from the geiger counter, the data are the same and always increasing. How can I solve it?
#define PRINT_DEBUG_MESSAGES
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <IFTTTMaker.h>
#include <ThingSpeak.h>
#include <SSD1306.h>
//#include <credentials.h> // or define mySSID and myPASSWORD and THINGSPEAK_API_KEY
#define LOG_PERIOD 20000 //Logging period in milliseconds
#define MINUTE_PERIOD 60000
#define WIFI_TIMEOUT_DEF 30
#define PERIODE_THINKSPEAK 20000
#ifndef CREDENTIALS
// WLAN
#define mySSID ""
#define myPASSWORD ""
//IFTT
#define IFTTT_KEY "......."
// Thingspeak
#define SECRET_CH_ID 000000 // replace 0000000 with your channel number
#define SECRET_WRITE_APIKEY "XYZ" // replace XYZ with your channel write API Key
#endif
// IFTTT
#define EVENT_NAME "Radioactivity" // Name of your event name, set when you are creating the applet
IPAddress ip;
WiFiClient client;
WiFiClientSecure secure_client;
IFTTTMaker ifttt(IFTTT_KEY, secure_client);
SSD1306 display(0x3c, 5, 4);
volatile unsigned long counts = 0; // Tube events
unsigned long cpm = 0; // CPM
unsigned long previousMillis; // Time measurement
const int inputPin = 7;
unsigned int thirds = 0;
unsigned long minutes = 1;
unsigned long start = 0;
unsigned long entryThingspeak;
unsigned long currentMillis = millis();
unsigned long myChannelNumber = SECRET_CH_ID;
const char * myWriteAPIKey = SECRET_WRITE_APIKEY;
#define LOG_PERIOD 20000 //Logging period in milliseconds
#define MINUTE_PERIOD 60000
void ISR_impulse() { // Captures count of events from Geiger counter board
counts++;
}
void displayInit() {
display.init();
display.flipScreenVertically();
display.setFont(ArialMT_Plain_24);
}
void displayInt(int dispInt, int x, int y) {
display.setColor(WHITE);
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.drawString(x, y, String(dispInt));
display.setFont(ArialMT_Plain_24);
display.display();
}
void displayString(String dispString, int x, int y) {
display.setColor(WHITE);
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.drawString(x, y, dispString);
display.setFont(ArialMT_Plain_24);
display.display();
}
/****reset***/
void software_Reset() // Restarts program from beginning but does not reset the peripherals and registers
{
Serial.print("resetting");
esp_restart();
}
void IFTTT(String event, int postValue) {
if (ifttt.triggerEvent(EVENT_NAME, String(postValue))) {
Serial.println("Successfully sent to IFTTT");
} else
{
Serial.println("IFTTT failed!");
}
}
void postThingspeak( int value) {
// Write to ThingSpeak. There are up to 8 fields in a channel, allowing you to store up to 8 different
// pieces of information in a channel. Here, we write to field 1.
int x = ThingSpeak.writeField(myChannelNumber, 1, value, myWriteAPIKey);
if (x == 200) {
Serial.println("Channel update successful.");
}
else {
Serial.println("Problem updating channel. HTTP error code " + String(x));
}
}
void setup() {
Serial.begin(115200);
displayInit();
ThingSpeak.begin(client); // Initialize ThingSpeak
displayString("Welcome", 64, 15);
Serial.println("Connecting to Wi-Fi");
WiFi.begin(mySSID, myPASSWORD);
int wifi_loops = 0;
int wifi_timeout = WIFI_TIMEOUT_DEF;
while (WiFi.status() != WL_CONNECTED) {
wifi_loops++;
Serial.print(".");
delay(500);
if (wifi_loops > wifi_timeout)
{
software_Reset();
}
}
Serial.println();
Serial.println("Wi-Fi Connected");
display.clear();
displayString("Measuring", 64, 15);
pinMode(inputPin, INPUT); // Set pin for capturing Tube events
interrupts(); // Enable interrupts
attachInterrupt(digitalPinToInterrupt(inputPin), ISR_impulse, FALLING); // Define interrupt on falling edge
unsigned long clock1 = millis();
start = clock1;
}
void loop() {
if (WiFi.status() != WL_CONNECTED)
{
software_Reset();
}
if (currentMillis - previousMillis > LOG_PERIOD) {
previousMillis = currentMillis;
cpm = counts * MINUTE_PERIOD / LOG_PERIOD;
//cpm=105;
counts = 0;
display.clear();
displayString("Radioactivity", 64, 0);
displayInt(cpm, 64, 30);
if (cpm > 100 ) IFTTT( EVENT_NAME, cpm);
}
// Serial.print("minutes: ");
// Serial.println(String(minutes));
//cpm = counts * MINUTE_PERIOD / LOG_PERIOD; this is just counts times 3 so:
cpm = counts / minutes;
if (millis() - entryThingspeak > PERIODE_THINKSPEAK) {
Serial.print("Total clicks since start: ");
Serial.println(String(counts));
Serial.print("Rolling CPM: ");
Serial.println(String(cpm));
postThingspeak(cpm);
entryThingspeak = millis();
}
// if ( thirds > 2) {
// counts = 0;
// thirds = 0;
// }
}
This is based on this work on GITHUB
Your code never updates the value of currentMillis. You set it equal to millis at global scope, likely before init is called and before millis even has a value and then you just leave it with that value. You're not telling that variable to call millis every time, you're just giving it the value of millis at that one instant. You need a line in loop to update that variable.
Because of that, this section never runs:
if (currentMillis - previousMillis > LOG_PERIOD) {
previousMillis = currentMillis;
cpm = counts * MINUTE_PERIOD / LOG_PERIOD;
//cpm=105;
counts = 0;
display.clear();
displayString("Radioactivity", 64, 0);
displayInt(cpm, 64, 30);
if (cpm > 100 ) IFTTT( EVENT_NAME, cpm);
}
and counts never gets set back to 0. That's why you see an ever increasing number.
You're also using this minutes variable as if it will count something, but you never add to it. So it just stays at 1 forever as far as I can tell.
I'm doing synchronization blinking with three XBee module and Arduino Uno,
the first is master, second is slave/master and the other one is a slave.
The master is going to give the command for both slave/master and slave to blinking, and when the master is switch off, the slave/master will taking over his job giving the command to blinking.
But the slave/master didn't go so well because of the coding didn't right.
Can anyone take a look at my coding and show me what is wrong with my coding.
Master Coding =
#include <SoftwareSerial.h>
#define Dout 2
#define Din 3
//#define LED 9
SoftwareSerial XBee(Dout, Din);
//char XBee_message;
int MasterSignalSent = 0;
const long interval = 2500;
unsigned long previousMillis = 0;
void setup() {
Serial.begin(9600);
XBee.begin(9600);
pinMode(13, OUTPUT);
}
void loop(){
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
Serial.println(currentMillis);
previousMillis = currentMillis;
{
delay(1500);
SendMasterSignal();//+
MasterSignalSent = 1;
delay(1000);
SendSyncSignal();//-
BlinkLed();
MasterSignalSent = 0;
}
}
}
void SendMasterSignal()
{
Serial.println("SendingMasterSignal. . .");
XBee.write('+');
}
void SendSyncSignal()
{
Serial.println("SendingSyncSignal. . .");
XBee.write('-');
}
void BlinkLed()
{
digitalWrite(13, HIGH);
delay(250);
digitalWrite(13, LOW);
//delay(2200);
}
Slave/Master Coding =
#include <SoftwareSerial.h>
#define Dout 2
#define Din 3
SoftwareSerial XBee (Dout, Din);
const long interval = 2500;
unsigned long previousMillis = 0;
int MasterSignalReceived = 0;
int ReceiveSyncSignal = 0;
int MasterSignalSent = 0;
char XBee_signal;
void setup() {
Serial.begin(9600);
XBee.begin(9600);
pinMode(13, OUTPUT);
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
while(XBee.available()){
XBee_signal = XBee.read();
Serial.println(XBee_signal);
delay(1500);
if (MasterSignalReceived == 0)
{
BecomeMaster();
}
else if (MasterSignalReceived == 1)
{
if (XBee_signal = '-'){
BlinkLed();
(MasterSignalReceived = 0);
}
else{
digitalWrite(13, LOW);
}
}
}
}
}
void BecomeMaster()
{
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
Serial.println(currentMillis);
previousMillis = currentMillis;
{
delay(1500);
SendMasterSignal();
MasterSignalSent = 1;
delay(2500);
SendSyncSignal();
BlinkLed();
MasterSignalSent = 0;
}
}
}
void SendMasterSignal()
{
XBee.write('+');
Serial.println("SendMasterSignalDone");
}
void SendSyncSignal()
{
XBee.write('-');
Serial.println("SendSyncSignalDone");
}
void BlinkLed()
{
digitalWrite(13, HIGH);
delay(1000);
digitalWrite(13, LOW);
}
The slave is waiting for the command to blinking but the slave/master didn't send any command as the coding write when the master switches off.
I'm trying to see if I can combine tasks that are currently being handled by two separate Arduino Unos onto a single Uno. I was shown the Adafruit guide to "multi-tasking" on the Arduino (Link) and thought I would give it a try.
I feel like I'm missing something really obvious, but my code is just not working...
I'm controlling a series of solenoids. They need to each act based on individual timing. I created a Solenoid class that handles telling the solenoid when to start and then monitor when to close it. For the life of me I can't see where my error is, but I never wind up satisfying my end condition.
class Solenoid {
//Class Variables
int solenoidPin;
long chargeTime;
long ventTime;
bool started = false;
unsigned long startMillis;
unsigned long endMillis;
unsigned long previousMillis;
int solenoidState;
//Constructor
public:
Solenoid(int pin, long charge, long vent) {
solenoidPin = pin;
pinMode(solenoidPin, OUTPUT);
chargeTime = charge;
ventTime = vent;
solenoidState = LOW;
previousMillis = 0;
}
void Start() {
Serial.println("Start called");
started = true;
}
void Update() {
//Check to see if it is time to change the state of the solenoid
unsigned long currentMillis = millis();
Serial.println("Update");
if((started == true) && (currentMillis-previousMillis <= chargeTime)) {
//Run
Serial.print("Run: Charge Time=");
Serial.print(chargeTime);
Serial.print(" current-previous=");
Serial.println(currentMillis-previousMillis);
previousMillis = currentMillis;
} else if ((started == true) && (currentMillis-previousMillis >= chargeTime)){
//Stop
Serial.println("Stop");
}
}
};
//Setup the solenoids
Solenoid solenoid1(13, 70, 70);
void setup() {
Serial.begin(115200);
Serial.println("Ready");
solenoid1.Start();
solenoid1.Update();
solenoid1.Update();
solenoid1.Update();
solenoid1.Update();
solenoid1.Update();
}
I'm just running everything in setup so I can see a few runs.
Can you help me with my clearer stupid mistake?
It's possible that the entire setup() void is executing faster than 70ms, meaning you never get to you end position before the 5 calls to solenoid1.Update() complete.
Try this:
class Solenoid {
//Class Variables
int solenoidPin;
long chargeTime;
long ventTime;
bool started = false;
unsigned long startMillis;
unsigned long endMillis;
unsigned long previousMillis;
int solenoidState;
//Constructor
public:
Solenoid(int pin, long charge, long vent) {
solenoidPin = pin;
pinMode(solenoidPin, OUTPUT);
chargeTime = charge;
ventTime = vent;
solenoidState = LOW;
previousMillis = 0;
}
void Start() {
Serial.println("Start called");
started = true;
}
void Update() {
//Check to see if it is time to change the state of the solenoid
unsigned long currentMillis = millis();
Serial.println("Update");
if((started == true) && (currentMillis-previousMillis <= chargeTime)) {
//Run
Serial.print("Run: Charge Time=");
Serial.print(chargeTime);
Serial.print(" current-previous=");
Serial.println(currentMillis-previousMillis);
previousMillis = currentMillis;
} else if ((started == true) && (currentMillis-previousMillis >= chargeTime)){
//Stop
Serial.println("Stop");
}
}
};
//Setup the solenoids
Solenoid solenoid1(13, 70, 70);
void setup() {
Serial.begin(115200);
Serial.println("Ready");
solenoid1.Start();
}
void loop(){
solenoid1.update()
}
The rest looks fine to me; if you still have issues try using explicit variable declarations instead of your constructor to troubleshoot if that's the issue.
Turns out I was erasing my own counter by setting previousMillis = currentMillis. Once I killed that, it started working. I added some other functionality since then, like a delayed start, but this is primarily the same code.
void Update() {
//Check to see if it is time to change the state of the solenoid
unsigned long currentMillis = millis();
if((started == true) && (currentMillis - startMillis <= startDelay)) {
//keep waiting
Serial.println("Waiting");
} else if((started == true) && (currentMillis - startMillis < (chargeTime + startDelay) )) {
//Run
Serial.print("Run ");
Serial.println(currentMillis - startMillis);
digitalWrite(solenoidPin, HIGH);
} else if ((started == true) && (currentMillis - startMillis >= (chargeTime + startDelay) )){
//Stop
Serial.print("Stop ");
Serial.println(currentMillis - startMillis);
digitalWrite(solenoidPin, LOW);
started = false;
}
}
My goal is to transfer a speed value from an encoder from a slave Arduino to a master Arduino via SPI. I am currently getting zeros on the master side serial print and I'm not sure what I am doing wrong. I have increased the amount of time to wait several times to see if it was a processing time issue but I had it waiting for 100mS with still no change. I know an unsigned int is 4 bytes and I am unsure if a union is the best option in this case seeing I might be overwriting my data due to the separate interrupts but I am unsure. I thought to use a struct since I'll have to move to transferring an array of floats and ints over SPI from various sensors including this encoder later. Below is my code and thank you for any help received:
Slave
#include "math.h"
#define M_PI
byte command = 0;
const int encoder_a = 2; // Green - pin 2 - Digital
const int encoder_b = 3; // White - pin 3 - Digital
long encoder = 0;
int Diameter = 6; // inches
float previous_distance = 0;
unsigned long previous_time = 0;
void setup (void)
{
Serial.begin(115200);
pinMode(MOSI, INPUT);
pinMode(SCK, INPUT);
pinMode(SS, INPUT);
pinMode(MISO, OUTPUT);
// turn on SPI in slave mode
SPCR |= _BV(SPE);
// turn on interrupts
SPCR |= _BV(SPIE);
pinMode(encoder_a, INPUT_PULLUP);
pinMode(encoder_b, INPUT_PULLUP);
attachInterrupt(0, encoderPinChangeA, CHANGE);
attachInterrupt(1, encoderPinChangeB, CHANGE);
}
// SPI interrupt routine
ISR (SPI_STC_vect)
{
union Data{
float f;
byte buff[4];}
data;
byte c = SPDR;
data.f = assembly_speed();
command = c;
switch (command)
{
// no command? then this is the command
case 0:
SPDR = 0;
break;
// incoming byte, return byte result
case 'a':
SPDR = data.buff[0];
break;
// incoming byte, return byte result
case 'b':
SPDR = data.buff[1];
break;
// incoming byte, return byte result
case 'c':
SPDR = data.buff[2];
break;
// incoming byte, return byte result
case 'd':
SPDR = data.buff[3];
break;
}
}
void loop (void)
{
// if SPI not active, clear current command
if (digitalRead (SS) == HIGH)
command = 0;
}
void encoderPinChangeA()
{
encoder += digitalRead(encoder_a) == digitalRead(encoder_b) ? -1 : 1;
}
void encoderPinChangeB()
{
encoder += digitalRead(encoder_a) != digitalRead(encoder_b) ? -1 : 1;
}
float distance_rolled()
{
float distance_traveled = (float (rotation()) / 8) * PI * Diameter;
return distance_traveled;
}
int rotation()
{
float eigth_rotation = encoder / 300;
return eigth_rotation;
}
float assembly_speed()
{
float current_distance = (float (rotation()) / 8) * PI * Diameter;
unsigned long current_time = millis();
unsigned long assemblySpeed = (((current_distance - previous_distance) /
12) * 1000) / (current_time - previous_time); // gives ft/s
previous_distance = current_distance;
previous_time = current_time;
return assemblySpeed;
}
Master
#include <SPI.h>
void setup (void)
{
pinMode(MOSI, OUTPUT);
pinMode(MISO, INPUT);
pinMode(SCK, OUTPUT);
pinMode(SS, OUTPUT);
Serial.begin (115200);
Serial.println ();
digitalWrite(SS, HIGH);
SPI.begin ();
SPI.setClockDivider(SPI_CLOCK_DIV8);
}
byte transferAndWait (const byte what)
{
byte a = SPI.transfer (what);
delayMicroseconds(10000);
return a;
}
union Data
{
float f;
byte buff[4];
}
data;
void loop (void)
{
digitalWrite(SS, LOW);
transferAndWait ('a');
data.buff[0] = transferAndWait ('b');
data.buff[1] = transferAndWait ('c');
data.buff[2] = transferAndWait ('d');
data.buff[3] = transferAndWait (0);
digitalWrite(SS, HIGH);
Serial.print("data.f = ");Serial.print(data.f);Serial.println(" Ft/s");
delay(200);
}
I have a serial application that runs from a nano into a current loop driver.
Now if I connect the Tx straight to the Rx the led is set to HIGH but if I link the Tx/Rx to the current loop board the LED isnt set at all. I have even added a serial to usb monitor to confirm that the current loop board is returning the same hex as is being passed. Any suggestions?
int timeout = 0;
void setup() {
// put your setup code here, to run once:
pinMode(13, OUTPUT);
Serial.begin(4800,SERIAL_8E1);
//Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
//delay(10000);
byte inByte1 = 0xF1;
byte inByte2 = 0x10;
byte inByte3 = 0xB0;
//if(timeout == 0)
//{
Serial.write(inByte1);
Serial.write(inByte2);
Serial.write(inByte3);
//}
//timeout = timeout+1;
//if(timeout == 50)
//{
// timeout=0;
//}
//delay(80);
byte inByte4 = 0xE1;
//Serial.println(Serial.available());
while (!Serial.available()) {
//timeout =0;
//byte inChar = Serial.read();
//Serial.println(inChar);
//digitalWrite(13, HIGH);
//if(inChar == inByte4)
//{
// digitalWrite(13, HIGH);
//}
Serial.write(inByte1);
Serial.write(inByte2);
Serial.write(inByte3);
delay(80);
}
while (Serial.available()) {
//timeout =0;
//byte inChar = Serial.read();
//Serial.println(inChar);
digitalWrite(13, HIGH);
//if(inChar == inByte4)
//{
// digitalWrite(13, HIGH);
//}
}
}
String ReadResult(Stream &serial)
{
int serialState = 0;
String content = "";
char character;
long interval = 10000;
//unsigned int timeout = 0;
unsigned long currentMillis = millis();
long previousMillis = millis();
while ( !serial.available() && serialState != 1) {
currentMillis = millis();
if(currentMillis - previousMillis > interval){
serialState = 1;
}
}
//timeout = 0;
//while (serial.available()) {
// character = serial.read();
// content += character;
//}
return content;
};
The driver that I was feeding to was not returning thecorrect voltage