Trouble with boolean value returning twice (Arduino) - c++

I'm working with a project that involves a Arduino UNO card and JAVA. The Arduino UNO would be the client and JAVA the server.
The problem is that my verify function is returning 0 twice when it's false, why does it do that and if true it returns 1 and 0 which is weird.
I just want it to return once, and not false false like the example here:
#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0F, 0x50, 0x35 };
IPAddress arduino(192,168,0,12);
IPAddress server(192,168,0,15);
EthernetClient client;
String username[] = {"Admin","Skut","Arbek","Kubda"};
String password[] = {"12344","stra","124ssgra","!#ยค%"};
String readString;
void setup() {
Serial.begin(9600);
Ethernet.begin(mac,arduino);
Serial.println("Connecting...");
if (client.connect(server, 8888)){
Serial.println("Connected to Server");
}
else {
Serial.println("Connecting failed");
}
}
boolean verify(String firstText, String secondText){
for(int i = 0; i <= 3 ; i++){
if((username[i] == firstText ) && (password[i] == secondText)){
return true;
}
}
return false;
}
void clientRead() {
while (client.available()) {
//delay(10);
if (client.available() >0) {
char c = client.read();
readString += c;
}
}
}
void loop(){
if (client.available() > 0){
readString = "";
clientRead();
Serial.println(readString);
int n = readString.length();
int commaIndex = readString.indexOf(';');
int lastIndex = readString.lastIndexOf(n);
String firstText = readString.substring(0, commaIndex);
String secondText = readString.substring(commaIndex + 1 , lastIndex);
Serial.println(firstText);
Serial.println(secondText);
Serial.println(verify(firstText, secondText));
}
if (!client.connected()){
Serial.println("Server disconnected!");
client.stop();
client.flush();
while(true);
}
}
I've tried sending ( Admin;12344 ) to the arduino from the server and this is what I get:
Connecting...
Connected to Server
Admin;12344
Admin
12344
1
0

while (client.available())
is not reliable. It might terminate earlier than what you expect depending on the relative speed of the device. Most probably you are getting partial data on the first try and another batch on second one (probably only \n). Instead of relying on available, use a marker to end the data.

The problem lies with what is being sent. If you look at the hex values of your output you will notice 7 CRLF between the 1 and 0. One of those belongs to the println of 1. The next 6 is exactly the output of 3 println. What is being printed 3 times? One CRLF, thats all. Because of the way you do the substrings all three outputs:
Serial.println(readString);
Serial.println(firstText);
Serial.println(secondText);
will print the very same CRLF along with their respective CRLF of the println.
So your answer is that you are sending a CRLF at the end of the line which is sent to the Arduino. Consider Cem Kalyoncu's answer about how to properly handle the reading and also do not send a CRLF to the Arduino at the end of the authentication line and you will most probably be fine.
I also suggest you read up on why not to use String in arduino. It is a world of memory and space problems you bring forth if you keep on using it.

Instead of if((username[i] == firstText ) && (password[i] == secondText)), try to use if(( firstText.equals(username[i]) ) && ( secondText.equals(password[i]) ))
I think the == don't compare the value of strings.

Related

Serial.write(5) not able to send decimal?

I am trying, as a test to Serial.write the int value: 5, to serial monitor, and if received, i want to print the the text "SUCCESS!" to the serial monitor.
But when writing Serial.write((int)5); All i get in the serial monitor is:
I have tried using Serial.println(5); which works fine, but then i am not able to read it.
My code:
enum read_states {
Modtag_Adresse,
Modtag_Bit_Position_I_Adresse,
Modtag_Bit_Position_Vaerdi
};
enum read_states state;
void setup() {
state = Modtag_Adresse;
Serial.begin(9600);
}
void loop() {
if(state == Modtag_Adresse) {
Serial.write((int)5);
delay(1000);
if(Serial.available() > 0) {
int serialReceived = Serial.read();
if(serialReceived >= 0) {
// Receive value 5
Serial.print("SUCCESS!!");
}
}
}
else if(state == Modtag_Bit_Position_I_Adresse) {
//
}
else if(state == Modtag_Bit_Position_Vaerdi) {
//
}
else {
// Failure.
}
}
Serial.write(5) sends the byte 5 to the computer. It appears as a square, because it's not an ASCII code of a letter or number or symbol.
Serial.print(5) sends the ASCII code for 5 (which is 53).
The reason you can't read what you wrote is because Serial.write sends data to the computer and Serial.read returns data received from the computer. If it read data from the Arduino program, it would be pointless because you don't need to use serial for that.

Arduino string comparison not working when using String str_out = String((char*)buf);

I am successfully receiving data over RF on a second Arduino. However I am trying to compare the incoming string so that I can call a method when there is a match. The "if" block is never executed. I am just trying to compare the strings that are incoming. It's printing the correct values to the serial monitor but the block is never executed. Maybe because this is using a pointer to a string (don't shoot me)? I am not that familiar with C or C++. I have tried several of the string comparison methods in the Arduino docs but no joy? Any reccomendations?
void loop()
{
// Set buffer to size of expected message
uint8_t buf[7];
uint8_t buflen = sizeof(buf);
// Check if received packet is correct size
if (rf_driver.recv(buf, &buflen))
{
// Message received with valid checksum
Serial.print("Message Received: ");
String str_out = String((char*)buf);
Serial.println(str_out); /
if (str_out == "plasma1") { // this is never executed wtf!!!
plasmaSequenceOne();
} else if (str_out == "plasma2") {
plasmaSequenceTwo();
} else if (str_out == "plasma3") {
plasmaSequenceThree();
} else if (str_out == "plasma4") {
plasmaSequenceFour();
}
}
}
Making Alex' self-response easier readable, and avoiding unnecessary String objects:
uint8_t buf[8];
uint8_t buflen = sizeof(buf)-1; // leave space for terminating 0
if (rf_driver.recv(buf, &buflen)) {
buf[buflen] = 0;
char* str_out = (char*)buf;
Serial.println (str_out);
if (strcmp(str_out, "plasma1")==0) plasmaSequenceOne();
...
}
This worked, thanks to #Remy Lebeau.

Incoming values to serial port are sometime corrupted or missing

I have written simple bluetooth transmitter and receiver on two arduino nano v3 boards. Bluetooth modules are HM-10 connected into hardware serial ports. It works, but on receiver side I often receive corrupted values and many values are missing. Where is a problem:
I am beginner in arduino. If it is possible a need to explain deeply. Thanks.
Transmitter code:
const long waitingInterval = 20000;
unsigned long lastSend = micros();
void setup()
{
Serial.begin(19200);
Serial.println("Started");
}
bool delay() {
if(micros() >= lastSend + waitingInterval) {
lastSend = micros();
return true;
}
return false;
}
void loop()
{
if(delay()) {
String mil = String(millis());
String sendingText = mil + ";" + mil + ";" + mil + ".";
Serial.println(sendingText);
}
}
Output of transmitter serial monitor interface:
10548;10548;10548.
10568;10568;10568.
10589;10589;10589.
10609;10609;10609.
10629;10629;10629.
10649;10649;10649.
10670;10670;10670.
10690;10690;10690.
10711;10711;10711.
10730;10730;10730.
10750;10750;10750.
10771;10771;10771.
10791;10791;10791.
10812;10812;10812.
10831;10831;10831.
10852;10852;10852.
10872;10872;10872.
10893;10893;10893.
10913;10913;10913.
10933;10933;10933.
10953;10953;10953.
10974;10974;10974.
10994;10994;10994.
11014;11014;11014.
11034;11034;11034.
11055;11055;11055.
11075;11075;11075.
11096;11096;11096.
11115;11115;11115.
Receiver code:
void setup() {
Serial.begin(19200);
Serial.println("Started");
}
void loop() {
if(Serial.available()) {
String incomingData = String();
char incomingChar = Serial.read();
if(incomingChar == '.') {
incomingData = bufferString;
Serial.print(bufferString);
bufferString = String();
} else {
bufferString += String(incomingChar);
return;
}
}
Output of receiver serial monitor interface:
10548;10548;10548
10568;10568;10568
10589;10589;10589
10609;10609;10609
10629;10629;10629
106410771
10791;10791;10791
10812;10812;10812
10831;10831;10831
10852;10852;10852
10872;10872;10872
10893;10893;11034;11034;11034
11055;11055;11055
11075;11075;11075
11096;11096;11096
11115;11115;11115
One problem is simply calling Serial.available() simply returns the number of bytes available to be read in the buffer; it could be exactly the number of bytes you need, it could be less, or more. Because of this, you might read extra data, too little, or too much data. More so, in higher level transmission protocols sometimes after a device receives data it will send an ACK(acknowledgement) back to the sender, saying it is ready for more data.
Edit** It should also be noted that the comment talking about mutex's isn't correct. Mutexes are typically used to synchronize code across multiple threads of execution on the same device. The key is that they are a shared resource across the thread's heap space. This is NOT the case when using two different arduino devices; thus, even if you could use them, it would be useless.
For your code, I would suggest the following edits to the transmitter:
#define MIN_TIMEOUT 3
void recieveAck(){
bool validAck = false;
uint8_t timeout_cnt = 0x00;
while(timeout_cnt < MIN_TIMEOUT){
//Wait for receiving device to respond with two bytes then send next
char incomingBytes[2];
Serial.readBytes(incomingBytes, 0x02);
if(incomingBytes[0] == 0xBB && incomingBytes[1] == 0xCC)
break;
timeout_cnt++;
}
}
void loop()
{
if(delay()) {
String mil = String(millis());
String sendingText = mil + ";" + mil + ";" + mil + ".";
Serial.println(sendingText);
recieveAck();
}
}
And to the receiver:
#define NEXT_INC_SIZE 2 //Expects one byte at a time
void sendAck(){
char outData[2];
outData[0] = 0xBB;
outData[1] = 0xCC;
Serial.write(outData, 2); //Write the ack data
}
void loop() {
if(Serial.available() >= NEXT_INC_SIZE){
char incomingBytes[2];
Serial.readByte(incomingBytes, NEXT_INC_SIZE); //Read exactly how many bytes you need
//Do stuff with the data here....
sendAck();
}
}

How to make an arduino serial loop (receive numbers continuously)

New to coding! I am trying to get text on my LED Matrix through serial data that is being sent in from processing.
My code works but the only problem is that though the serial data on processing is constant, the arduino code only reads the number once. This makes it so that the text will not scroll all the way through. How do I loop a serial read on arduino?
Here is the relevant portion of my code:
void loop()
{
if (Serial.available() > 0)
{
int matrixPinState = Serial.read();
// stage = Serial.read();
// analogWrite(matrixPin, stage);
if (matrixPinState == 1)
{
matrix.fillScreen(0);
matrix.setCursor(x, 0);
matrix.print(F("Im kind"));
if (--x < -30)
{
x = matrix.width();
if (++pass >= 8) pass = 0;
matrix.setTextColor(colors[pass]);
}
matrix.show();
delay(30);
}
}
}
When a byte(or you call it character, a data that is 8 bit long) is fetched by uart block(the hardware), it is buffered to input buffer so that programmer can read and process it.
In your case, when you send a character, it is fetched and put to the buffer and when you read it there is no more byte available to read unless you send to new one.
In short, read the pin state once. You can do something like:
int matrixPinState = 0
void setup() {
// do all your setup settings first
while (Serial.available() < 0) {
// wait here for the input
delay(30);
}
// got your input, read it
matrixPinState = Serial.read();
}
void loop()
{
if (matrixPinState == 1)
{
matrix.fillScreen(0);
matrix.setCursor(x, 0);
matrix.print(F("Im kind"));
if (--x < -30)
{
x = matrix.width();
if (++pass >= 8) pass = 0;
matrix.setTextColor(colors[pass]);
}
matrix.show();
delay(30);
}
}

arduino: program with else not working

#include <Servo.h>
Servo myservo; // create servo object to control a servo
int pos = 90;
String kontrolstr = "";
char kontrol;
void setup()
{
Serial.begin(9600);
myservo.attach(9);// attaches the servo on pin 9 to the servo object
}
void loop()
{
if(Serial.available())
{
kontrol=Serial.read(); // it reads from python voice recognition
kontrolstr.concat(kontrol);
}
if(kontrolstr== "right")
{pos += 30;
kontrol = '0';
kontrolstr = "";
}
else if(kontrolstr== "left")
{pos -= 30;
kontrol= '0';
kontrolstr = "";
}
myservo.write(pos);
delay(100);
}
It works with voice_command.py (which I wrote) on linux terminal. When code is like this, right after uploading this code to arduino, it works well until voice recognition understand a different word from "right" or "left". When voice command send to arduino another string different from "right" or "left", program still works without any error but after this point it starts not to respond "right" or "left" command anymore. To solve this I did this change. I put an 'else':
#include <Servo.h>
Servo myservo; // create servo object to control a servo
int pos = 90;
String kontrolstr = "";
char kontrol;
void setup()
{
Serial.begin(9600);
myservo.attach(9);// attaches the servo on pin 9 to the servo object
}
void loop()
{
if(Serial.available())
{
kontrol=Serial.read();
kontrolstr.concat(kontrol);
}
if(kontrolstr== "right")
{pos += 30;
kontrol = '0';
kontrolstr = "";
}
else if(kontrolstr== "left")
{pos -= 30;
kontrol= '0';
kontrolstr = "";
}
else { // I write this to make it work..
kontrol = '0';
kontrolstr = "";
}
myservo.write(pos);
delay(100);
}
However, now it is not responding "right" and "left" command too. How can I solve this problem?
The Problem
The problem you are having is that your Serial.available() block is only reading one byte from the Serial buffer in each iteration of the loop. As a consequence, when your servo sends the word "right", the Serial buffer is "right". The first iteration through loop() gives "r" as the value for kontrolstr.
Without the else block, on the second loop, kontrolstr is set to ri, then rig, then righ, etc, and is only reset when left or right are found. This is also what causes the problem of left and right not being reached if another word has been recognized - kontrolstr would have been set to , e.g. "horse", this is not recognized, so then when it sends "right", you get "horseright", etc.
With the else block, on the first loop, kontrolstr is "r", so it hits the else block, and resets the string. On the second loop, kontrolstr is "i", it hits the else block and resets the string, etc, never reaching the relevant control block.
Possible solutions
The start of the solution is to read the entire Serial buffer before processing it, so replace the block starting with if(Serial.available() to:
while(Serial.available())
{
kontrol = Serial.read();
kontrolstr.concat(kontrol);
}
This will read the entire buffer in the first loop, so as long as all the data has been sent between iterations of the loop, your problem will be solved. However, it takes a non-zero amount of time to send data over a Serial port, so it's possible that your loop() iteration triggers in the middle of a send, in which case the Serial buffer might be something like "rig", which won't match "right" or "left", will be reset, then in the next loop you'll get "ht", and again it will be reset - the trigger will be missed.
If possible, I think the best solution would be to have your servo send the control words with a delimiter between them, e.g. \n. If your servo sends "right\nanother word\nleft\n", then you can wait for entire words to come in before processing them. You can do this by changing your loop() to:
void loop()
{
kontrolstr = ""; // Reset on each iteration of the loop
while(Serial.available())
{
kontrol = Serial.read();
// If we reach the delimiter, stop reading from the Serial buffer
if (control == '\n') {
break;
}
kontrolstr.concat(kontrol);
}
if(kontrolstr== "right") {
pos += 30;
} else if(kontrolstr== "left") {
pos -= 30;
}
myservo.write(pos);
delay(100);
}
Of course, this assumes that you're OK with allowing extra words to accumulate in the Serial buffer (seems fine since the buffer wasn't filling up even when you were reading only 1 character every 100ms). However, if it does happen that the Serial buffer is overflowing, then you can create a second string bufferstring and always append whatever is in the Serial buffer to that string, then on each iteration of the loop, pull out the oldest command, giving:
#include <Servo.h>
Servo myservo; // create servo object to control a servo
int pos = 90;
String kontrolstr = "";
String bufferstring = "";
char kontrol;
void setup()
{
Serial.begin(9600);
myservo.attach(9);// attaches the servo on pin 9 to the servo object
}
void loop()
{
// Read whatever's in the Serial port into the buffer string
while(Serial.available())
{
kontrol = Serial.read();
// If we reach the delimiter, stop reading from the Serial buffer
bufferstring.concat(kontrol);
}
// Split the string by the delimiter
int delimiter_loc = bufferstring.indexOf('\n');
if (delimiter_loc != -1) {
// Get the first delimiter_loc characters (doesn't include the delimiter)
kontrolstr = bufferstring.substring(0, delimiter_loc);
// Remove all the characters up to and including the delimiter_loc
bufferstring.remove(0, delimiter_loc + 1);
}
if(kontrolstr== "right") {
pos += 30;
} else if(kontrolstr== "left") {
pos -= 30;
}
// Reset on each iteration of the loop
kontrolstr = "";
myservo.write(pos);
delay(100);
}