Recieved String to useable variable in Arduino - c++

I'm trying to use data sent via Bluetooth from a mobile app to the Arduino. There will be 2 strings received dependent on the function required.
First function: When the string "ledon" or "ledoff" received turn on or turn off an led.
Second Function: from the app I get the data a user has typed into 2 boxes, one a text box the other a password box, this is received by the Arduino as one string with comma's as a delimiter so the string can be separated into it's component parts, which in this case are an "ssid name" and a "network key". These details I will be intending to write to an onboard sd card so that the wifi module will be able to logon to the network that the ssid and network key are relevant too.
So far I can get the led light to do as it should, I can also get the string read, separated by the delimiter and printed out to the serial monitor. However when I try to combine the two codes the led function fails to turn on or off the led light although the correct command is printed into the serial monitor. I have researched how to solve this trying each requirement as a standalone function and calling them in the loop section, which individually they work but when called together again the led fails to come on.
This is the code i'm presently using:
const int ledPin = 11;
String readString;
void setup() {
Serial.begin(9600);
pinMode (ledPin, OUTPUT);
}
void loop() {
while (Serial.available()) {
delay(3);
char c = Serial.read();
readString += c;
}
//turns led on or off
if (readString.length() >0) {
Serial.println(readString);
if (readString == "ledon")
{
digitalWrite (ledPin, HIGH);
}
if (readString == "ledoff")
{
digitalWrite (ledPin, LOW);
}
readString="";
//seperates the string into 2 lines using the delimiter ","
String first = Serial.readStringUntil(',');
Serial.read(); //next character is comma, so skip it using this
String second = Serial.readStringUntil(',');
Serial.read();
Serial.println(first);
Serial.println(second);
readString="";
}
}
If I comment out the string part of the code the led turns on and off fine, if I try and run the code as is the code prints everything you would expect but the led doesn't come on.
I'm pretty new to Arduino,c and c++ and I cannot seem to figure this out so any help would be great.
The app I'm using to control this is being built in Mit's App Inventor 2

I have finally resolved this.
I decided to look at other logical steps to find a solution.
I considered the issue could be having different strings that did different things which may be conflicting in some way.
In my research I found reference to the fact that the Bluetooth module HC-05 has 2 pins that in my case were not being utilised, the key pin and the state pin, in this stack overflow discussion Tell when Bluetooth module connects on Arduino and decided this logic of using the "State pin" to signify Bluetooth connection would negate the possibility of any conflicts within the String logic.
Once I had figured out the best way to place and order the "where" statements I managed to get the functionality at this point in my project which then allows me to move on to the next step in the development.
The code I have now arrived at:
const int ledPin1 = 11;
const int ledPin2 = 4;
String readString;
boolean BTconnected = false;
void setup() {
Serial.begin(9600);
pinMode (ledPin1, OUTPUT);
pinMode (ledPin2, INPUT);
}
void loop() {
while (!BTconnected)
{
if ( digitalRead(ledPin2)==HIGH) { BTconnected = true;};
}
digitalWrite(ledPin1, HIGH);
Serial.println("HC-05 is now connected");
Serial.println("");
while (BTconnected)
{
if ( digitalRead(ledPin2)==LOW) { BTconnected = false;
digitalWrite(ledPin1, LOW);
Serial.println("HC-05 is now disconnected");
Serial.println("");
};
while (Serial.available())
{
delay(3);
char c = Serial.read();
readString += c;
}
if (readString.length() >0) {
//Serial.println(readString);
//readString="";
String first = Serial.readStringUntil(',');
Serial.read(); //next character is comma, so skip it using this
Serial.println(first);
//readString="";
String second = Serial.readStringUntil(',');
Serial.read();
Serial.println(second);
Serial.println("");
//readString="";
}
}
}

Related

Strange characters after JSON

I have an application that gets the Arduino Nano information and sends it to ESP-01 via UART. The ESP-01 send this to MQTT.
NANO CODE:
#include "DHTesp.h"
#include <ArduinoJson.h>
#include <SoftwareSerial.h>
#define gasSensor A1
#define dhtPin 5
#define rain A2
#define soil A3
#define ldr A4
DHTesp dht;
void setup() {
Serial.begin(115200);
pinMode(gasSensor, INPUT);
pinMode(rain, INPUT);
pinMode(soil, INPUT);
pinMode(ldr, INPUT);
digitalWrite(dhtPin, LOW);
dht.setup(dhtPin, DHTesp::DHT11);
}
void loop() {
delay(dht.getMinimumSamplingPeriod());
float humidity = dht.getHumidity();
float temperature = dht.getTemperature();
DynamicJsonBuffer jBuffer;
JsonObject& measure = jBuffer.createObject();
JsonObject& data = jBuffer.createObject();
measure["gas"] = analogRead(gasSensor);
measure["humidity"] = humidity;
measure["temperature"] = temperature;
measure["heatindex"] = dht.computeHeatIndex(temperature, humidity, false);
measure["rain"] = analogRead(rain);
measure["soil"] = analogRead(soil);
measure["ldr"] = analogRead(ldr);
data["measure"] = measure;
data.printTo(Serial);
}
ESP-01 CODE:
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
const char* mqtt_server = "0.0.0.0";
WiFiClient espClient;
PubSubClient client(espClient);
char mystr[100];
void setup() {
Serial.begin(115200);
WiFi.begin("", "");
Serial.print("Connecting");
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println();
Serial.print("Connected to IP: ");
Serial.println(WiFi.localIP());
client.setServer(mqtt_server, 1883);
}
void loop() {
if (client.connect("ESP")) {
Serial.println("STATUS MQTT-ESP: OK");
while (true) {
Serial.readBytes(mystr, 108);
client.publish("esp", mystr);
delay(1000);
}
} else {
Serial.println("STATUS MQTT-ESP: OFF");
}
}
But, I'm getting strange characters into MQTT:
And, at the connection between NANO <-uart-> Computer, the JSON is normal:
Someone could help me?
Thanks.
I am basing this answer on a bit of assumptions as I don't have an Arduino at hand.
You send your data like this:
data.printTo(Serial);
This sends the string holding the formatted JSON data. This does not include the terminating 0 byte.
Then you receive it like this:
char mystr[100];
...
while(true){
Serial.readBytes(mystr, 108);
client.publish("esp", mystr);
delay(1000);
}
This has multiple errors:
You do not care if you got any bytes at all. The method returns the number of bytes but you do not handle the return value at all. If you got 0 bytes within the timeout value, you will just send the previous message again instead of waiting for valid data.
You cannot put 108 bytes into memory location of 100 bytes.
You put an array of char into the publish method that does not contain any termination. How should that method know how many characters are really part of the string?
Try this:
while(true){
size_t num = Serial.readBytes(mystr, sizeof(mystr)-1);
mystr[num] = 0;
client.publish("esp", mystr);
delay(1000);
}
You do not have any protocol that allows you to detect when a message starts or ends. UART communiation is a byte stream without any boundaries for datagrams. You must ensure that you know what belongs to a message and what does not. This also means that you can never know if you have a complete message in your receive bufffer or an incomplete or even more than one message. It's up to you to detect and split messages. Fixing this is a bit more complex. I can only give some hints what you need to do.
a) Detect message boundaries:
You might send some terminator like \n, 0 or similar after each JSON string and scan for this extra byte on receiver side.
Or you can send the length of the string before you send the string.
You could also just check on receiver side when you have a matching pair of {}. This would not require any change on sender side.
b) Collect messages:
Call your read function as long as it takes until you detect the end of a string.
You might need to use intermediate buffer to collect multiple read buffers.
c) Forward messages:
As soon as you detected the end of a message, forward it via publish function.
Then move the remaining content of your collection buffer to the start of that buffer.
If you immediately find the end of another message, repeat that step.
If you don't find any complete message, continue to collect more data until the next message is complete.

Receiving a sms from a specific number

I am working on a project where my Arduino ATMEGA328 interfaced in SIM900 GSM Shield will receive an sms from the specific number.
I was able to receive the message. But I want my GSM to only receive from a specific number. For example, i only want to receive from +639123456789 number only. Numbers like +639111112222 and +639998887777 and other will be discarded. Can anyone can help me?
EDIT: This is my code.
#include <SoftwareSerial.h>
#include <string.h>
char inchar; // Will hold the incoming character from the GSM shield
String s = "";
SoftwareSerial SIM900(2, 3);
void setup()
{
Serial.begin(9600);
// wake up the GSM shield
SIM900power();
SIM900.begin(9600);
delay(20000); // give time to log on to network.
SIM900.print("AT+CMGF=1\r"); // set SMS mode to text
delay(100);
SIM900.print("AT+CNMI=2,2,0,0,0\r");
// blurt out contents of new SMS upon receipt to the GSM shield's serial out
delay(100);
Serial.println("Ready...");
}
void SIM900power()
// software equivalent of pressing the GSM shield "power" button
{
digitalWrite(9, HIGH);
delay(1000);
digitalWrite(9, LOW);
delay(7000);
}
void loop()
{
if(SIM900.available() > 0)
{
if(SIM900.find("+639123456789 ") && SIM900.find("AUTO"))
{
Serial.println("AUTOMATIC asd");
SIM900.println("AT+CMGD=1,4");
}
}
}
I was able to receive the message. But I want my GSM to only receive
from a specific number.
Do you wish to stop the GSM from receiving SMS from unknown numbers, or do you want to output to serial when the conditions are met?
If it's the former, you may want to talk to your network provider, and consider the architectures pitfalls in this approach.
It immediately deletes the message once it does not satisfies the
condition
On that same if condition where you discard the sms if not sent from numXXX,
add an
else{
SIM900.print("AT+CNMI=2,2,0,0,0\r");
Serial.println("AUTOMATIC asd");
SIM900.println("AT+CMGD=1,4");
// or write high to led pin if that's what you want.......
}
Of course, it would help if we could see that sketch...

interfacing c++ to control motor stepper with arduino

I have tried to control motor stepper via arduino uno board with slider in visual C++.
but the servo didnot move at all.
here the program at PC side:
void CENVSConfigDlg::OnBnClickedButton1()
{
SetTimer(cTimer1,80,NULL);
}
void CENVSConfigDlg::OnTimer(UINT_PTR ID)
{
if(ID==cTimer1){
DWORD nbytes;
char buf[5];
sprintf(buf, "%d \n", val_test);
/* Open serial port. */
if(!WriteFile( hnd_serial, (void*)buf, 5, &nbytes, NULL )){MessageBox(L"Write Com Port fail!");return;}
}
and the program in arduino:
#include <Servo.h>
Servo servoMain;
int index=0;
String inputString;
void setup()
{
Serial.begin(9600);
servoMain.attach(9);
}
void loop()
{
int data;
while (Serial.available())
{
char inChar = (char)Serial.read();
if (inChar == '\n' || inChar == 'z')
{
data=stringToInt(inputString);
Serial.println(data); //
inputString="";
servoMain.write(data); //tambahannya
delay(50);
break;
}
if (inChar != 0)
{
inputString += inChar;
}
}
}
int stringToInt(String s)
{
char char_string[s.length()+1];
s.toCharArray(char_string, s.length()+1);
return atoi(char_string);
}
the pc i think is sending the data, but why the motor didnot working? any idea?
First off, does the serial link work at all? The number of ways that an RS232 link can not work, for both hardware and software reasons, is legendary. Unless you can show that the hardware can transfer data, it's pointless to look at your dedicated software. If you have a scope, use that to see if anything is being transmitted and then check that it arrives at the correct pin on the arduino input. If you have no access to a scope, a small LED and a 4.7K resistor can be used to indicate that there is data on the line - it will flicker with the data.

Arduino: AT Commands - Read the last line of the serial output using Serial.read()

I constantly pass AT commands to get GSM Signal Strength
My code copies the entire serial output
Kindly advise how to read the latest serial output (last line)
find the output below, in which i need to assign the output from last line (21,0) to the variable "signal"
My Output:
AT
OK
AT+CREG?
+CREG: 0,1
ok
AT+CSQ
+CSQ: 21,0
My code:
byte gsmDriverPin[3] = {
3,4,5};
char signal[10];
char inChar;
int index;
char inData[200];
void setup()
{
//Init the driver pins for GSM function
for(int i = 0 ; i < 3; i++){
pinMode(gsmDriverPin[i],OUTPUT);
}
digitalWrite(5,HIGH);//Output GSM Timing
delay(1500);
digitalWrite(5,LOW);
digitalWrite(3,LOW);//Enable the GSM mode
digitalWrite(4,HIGH);//Disable the GPS mode
delay(2000);
Serial.begin(9600); //set the baud rate
delay(5000);//call ready
delay(5000);
delay(5000);
start_GSM();
}
void loop()
{
Signal_Strength();
Serial.println("AT+CMGF=1");
delay(1000);
Serial.println("AT+CMGS=\"1234567890\"");//Change the receiver phone number
delay(1000);
Serial.println(signal);
delay(1000);
Serial.write(26);
}
void Signal_Strength(){
Serial.println("AT+CSQ");
delay(2000);
read_String();
strtok(inData, ",");
strcpy(signal,strtok(NULL, ","));
}
void read_String() {
index=0;
while(Serial.available() > 0) // Don't read unless
// there you know there is data
{
if(index < 199) // One less than the size of the array
{
inChar = Serial.read(); // Read a character
inData[index] = inChar; // Store it
index++; // Increment where to write next
inData[index] = '\0'; // Null terminate the string
}
}
}
void start_GSM(){
//Configuracion GPRS Claro Argentina
Serial.println("AT");
delay(2000);
Serial.println("AT+CREG?");
delay(2000);
}
First of all, you must seriously redo your AT command handling to
Read and parse the every single response line given back from the modem until you get a final result code. This applies for every single command line invocation, no exceptions whatsoever. See this answer for more details.
Never ever call delay in any code that handles AT commands. See this answer for more details about the risk of aborting the next command.
Before fixing these fundamental issues you cannot expect any successful behaviour. Parsing AT command responses is not that complicated, have a look at the source code for atinout for an example.

Why is no serial data available on my Arduino?

I've run the simple serial program on my Arduino Uno, which just echos whatever you type to it. This works perfectly when run in the Arduino Sketch IDE (v22).
int incomingByte = 0; // for incoming serial data
void setup() {
Serial.begin(115200); // opens serial port, sets data rate
}
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);
}
}
(Code taken from http://arduino.cc/en/Serial/Available)
However, I prefer not to use the Arduino IDE and would rather compile my C++ code with avr-g++, so I wrote this, which should function exactly the same as above:
extern "C" {
#include <avr/io.h>
}
#include <HardwareSerial.h>
extern "C" void __cxa_pure_virtual() { while(1); }
int main (void)
{
int incomingByte = 0;
Serial.begin(115200);
while (1) {
if (Serial.available() > 0) {
incomingByte = Serial.read();
//print as an ASCII character
Serial.print("received: ");
Serial.println(incomingByte, DEC);
}
}
return 1;
}
I compile and run it, but it doesn't work. I never see my text echoed back to me. I tried printing out the value of Serial.available() in the while(1) loop, and it's always zero. Whenever I type on the keyboard, I see the RX LED light up, but nothing happens after that. I can edit my code to successfully call Serial.println() as long as it's outside the Serial.available() conditional.
I've confirmed that my baud rate in my serial software is also set to 115200. And yes, my serial software is pointing to the right serial port.
What am I missing?
Arduino's original glue code looks like this:
#include <WProgram.h>
int main(void)
{
init();
setup();
for (;;)
loop();
return 0;
}
The init() stuff is missing in your code. init() is defined in $ARDUINO_HOME/hardware/arduino/cores/arduino/wiring.c, you can either link against it directly or just copy the code of init() into your code.
You probably have not properly initialized the UART port on the chip. This has to be done manually for microcontrollers, and the Arduino IDE was probably doing it for you. Check the AVR datasheet for your chip, specifically the serial port section.
Found the answer to my own question:
It turns out the HardwareSerial.h library relies on interrupts. This is something that is automagically taken care of for you when building with the Arduino IDE. If you aren't using the Arduino IDE (like me), then you must remember to enable interrupts on your own.
Just #include <avr/interrupt.h>, and call sei(); to turn on interrupts before you try to use the Serial Library.
cheers!