while...else Statement for Arduino - arduino

Is there a possibility to add an else after a while-Loop in Arduino, like there is in Java or C#? Something like this:
while(condition){
doThingA;
} else{
doThingB;
}

C# does not have while...else and I don't think Java has this construct either. Python has it and because the instructions in the else block are not executed only when you break from the loop you can emulate it as follows:
bool flag = TRUE;
while (condition)
{
if (anothercondition)
{
flag = FALSE;
break;
}
}
if (flag)
{
...
}

No maybe, it's not actually because it is based on embedded c, which includes syntaxes similar to c. So to conclude it simply can't. was a pleasure to help you.

ESPserial.print(params + '\n');
time = millis();
while(true) {
int avail = ESPserial.available();
if (avail) break;
if (millis() - time > 500) break;
}
do {
char ch = ESPserial.read();
data += ch;
} while (ESPserial.available());

You can't have a else after a whole loop but u can put a exclamation(!) before the statement like:
while (!condition)
orwhile(value1 != value2)

Related

AsyncTCP on ESP32 and Odd Heap/Socket Issues w/SOFTAP

I'm struggling with an issue where an ESP32 is running as a AP with AsyncTCP connecting multiple ESP32 clients. The AP receives some JSON data and replies with some JSON data. Without the handleData() function, the code runs 100% fine with no issues. Heap is static when no clients connect and issues only occur when clients start connecting.
Can anyone see anything with my code that could be causing heap corruption or other memory weirdness?
static void handleData(void* arg, AsyncClient* client, void *data, size_t len) {
int i = 0, j = 0;
char clientData[CLIENT_DATA_MAX];
char packetData[len];
char *packetBuf;
packetBuf = (char *)data;
clientData[0] = '\0';
for (i=0;i <= len;i++) {
packetData[j] = packetBuf[i]; //packetBuf[i];
if ((packetData[j] == '\n') || (i == len)) {
packetData[j] = '\0';
if ((j > 0) && (packetData[0] != '\n') && (packetData[0] != '\r')) {
// See sensorData() below...
parseData.function(packetData, clientData);
if (clientData != NULL) {
// TCP reply to client
if (client->space() > 32 && client->canSend()) {
client->write(clientData);
}
}
}
j = 0;
} else
j++;
}
}
void sensorData(void *data, void *retData) {
StaticJsonDocument<CLIENT_DATA_MAX> fields;
StaticJsonDocument<CLIENT_DATA_MAX> output;
char sensor[15] = "\0";
char MAC[18] = "\0";
char value[20] = "\0";
bool sendOK = false;
memcpy((char *)retData, "\0", 1);
DeserializationError error = deserializeJson(fields, (char *)data, CLIENT_DATA_MAX);
if (error) {
DEBUG_PRINTLN(F("deserializeJson() failed"));
return;
}
if (fields["type"])
strcpy(sensor, fields["type"]);
switch (sensor[0]) {
case 'C':
if (fields["value"])
strcpy(value, fields["value"]);
sendOK = true;
break;
case 'T': //DEBUG_PRINT(F("Temp "));
setExtTempSensor(fields["value"]);
sendOK = true;
break;
case 'N':
output["IT"] = intTempC; //Internal temp
output["B1"] = battLevels[0];
serializeJson(output, (char *)retData, CLIENT_DATA_MAX-1);
break;
}
if (sendOK) {
output["Resp"] = "Ok";
serializeJson(output, (char *)retData, CLIENT_DATA_MAX-1);
}
strcat((char *)retData, "\n");
}
static void handleNewClient(void* arg, AsyncClient* client) {
client->setRxTimeout(1000);
client->setAckTimeout(500);
client->onData(&handleData, NULL);
client->onError(&handleError, NULL);
client->onDisconnect(&handleDisconnect, NULL);
client->onTimeout(&handleTimeOut, NULL);
}
void startServer() {
server = new AsyncServer(WIFI_SERVER_PORT);
server->onClient(&handleNewClient, &server)
}
Using AsyncTCP on the ESP32 was having multiple issues. Heap issues, socket issues, assert issues, ACK timeouts, connection timeouts, etc. Swapping to AsyncUDP using the exact same code as shown above with romkey's changes, resolved all of my issues. (Just using romkey's fixes did not fix the errors I was having with AsyncTCP.) I don't believe the issue is with AsyncTCP but with ESP32 libraries.
Either you should declare packetData to be of length len + 1 or your for loop should iterate until i < len. Because the index starts at 0, packetData[len] is actually byte len + 1, so you'll overwrite something random when you store something in packetData[len] if the array is only len chars long.That something random may be the pointer stored in packetBuf, which could easily cause heap corruption.
You should always use strncpy() and never strcpy(). Likewise use strncat() rather than strcat(). Don't depend on having done the math correctly or on sizes not changing as your code evolves. strncpy() and strncat() will guard against overflows. You'll need to pass a length into sensorData() to do that, but sensorData() shouldn't be making assumptions about the available length of retData.
Your test
if (clientData != NULL) {
will never fail because clientData is the address of array and cannot change. I'm not sure what you're trying to test for here but this if will always succeed.
You can just write:
char sensor[15] = "";
you don't need to explicitly assign a string with a null byte in it.
And
memcpy((char *)retData, "\0", 1);
is equivalent to
((char *)retData)[0] = '\0';
What's the point of declaring retData to be void * in the arguments to sensorData()? Your code starts out with it being a char* before calling sensorData() and uses it as a char* inside sensorData(). void * is meant to be an escape hatch for passing around pointers without worrying about their type. You don't need that here and end up needing to extra casts back to char* because of it. Just declare the argument to be char* and don't worry about casting it again.
You didn't share the code that calls handleData() so there may well be issues outside of these functions.

Trying to extract longitude and latitude from gps using arduino and neo 6m module but the loop goes up to infinity

I'm new to arduino and trying to extract gps coordinate using neo 6m module using arduino but the loop is running till infinity. Can you please help me why it is not breaking.
void gpsEvent()
{
gpsString = "";
while (1)
{
while (gps.available() > 0) //Serial incoming data from GPS
{
char inChar = (char)gps.read();
gpsString += inChar;//store incoming data from GPS to temparary string str[]
i++;
// Serial.print(inChar);
if (i < 7)
{
if (gpsString[i-1] != test[i-1]) //check for right string
{
i = 0;
gpsString = "";
}
}
if (inChar == '\r')
{
if (i > 60)
{
gps_status = 1;
break;
}
else
{
i = 0;
}
}
}
if (gps_status)
break;
}
}
void get_gps()
{
gps_status = 0;
int x = 0;
while (gps_status == 0)
{
gpsEvent();
int str_lenth = i;
coordinate2dec();
i = 0;
x = 0;
str_lenth = 0;
}
}
I have called get_gps(); in the void setup() loop to initialize the system but the gpsEvent function which is used to extract the correct string from data is running till infinite can you pls help. The reference of the code is from https://circuitdigest.com/microcontroller-projects/arduino-based-accident-alert-system-using-gps-gsm-accelerometer
but have made few changes of my own but not in the programming for the gps module.
I think one of the errors is gpsString += inChar;.
This is not Python. You are adding the value of a character to a string pointer.
You should create a buffer with a maximum length, insert a char and check buffer overflow.
Also i seems not be defined. And in C is very bad practice to use global variables as you are doing. Keep one i in the function. Check again the string length.
In general, it seems you are using a language you do not know enough to write simple programs (string manipulation is basic on C). Either learn better C or look for a python implementation (or just link) of the gps library.

Why output is printed in asci code instead of integer ?dart

I don't know why output is printed in ascii code instead of integer value ,what wrong with my code ?
import 'dart:io';
void main() {
int n = 0;
print("input: ");
do {
n = stdin.readByteSync();
} while (n>1000 || n<0);
if (n % 4 == 0) {
print("output: ");
print(n);
n++;
} else {
print("output: ");
n--;
print(n);
}
}
Paste your code so it can be easier to help you.
I could have given you a fixed source code if you would have provided.
Instead, I'll try to explain:
Your stdin will be provided as a string, you read it as bytes so 5 will be come 35 as hex.
When you print it, my guess is that it will automatically be converted to a decimal value (53, and the output shows 52 because 53 % 4 = 1 and then to decrease with n-- before printing it so it become 52).
Those numbers like you said of the ASCII Table.
In order to fix it, make sure you have the string representation of the input (stdin). Then convert the value to integer: "2".toInt()
Edit:
I could have easily find the complete solution,
You need to get the stdin as a string first: readLineSync and convert it to int:
n = int.parse(stdin.readLineSync());
Note: Code not tested, but it's pretty straight forward.
Get the value as String using stdin.readLineSync() then parse it to int like below:
import 'dart:io';
void main() {
int n = 0;
print("input: ");
do {
n = int.parse(stdin.readLineSync());
} while (n>1000 || n<0);
if (n % 4 == 0) {
print("output: ");
print(n);
n++;
} else {
print("output: ");
n--;
print(n);
}
}

Deleting single character on lcd

While I have successfully cleared all the lcd display with the help of some guys here by a cheat code (because it doesn't really cleared the display)for (int i=0; i < 80; i++), Now I needed to delete single character on my lcd display.
Note:
I am using serial communication with my lcd module. I intensively search the internet but I could not find any solution, Is there anyone who had an Idea to do so?
The HD44870 command set has no provisions for deleting characters. You will need to read out all the following characters on the display, write them in the appropriate place, and then put one or more blank spaces after.
Here you have my example of entering password with keyboard and displaying it on the LCD:
bool enterPassword(char currentPassword[], byte lenghtMaxPassword)
{
byte nextChar = 0;
char changePassKeyPressed;
while(nextChar <= lenghtMaxPassword)
{
changePassKeyPressed = keyboard.getKey();
if(nextChar != lenghtMaxPassword)
{
if(!changePassKeyPressed)
{
continue;
}
else if(changePassKeyPressed=='#')
{
return false; // stop entering the password
}
else if(changePassKeyPressed=='*')
{
if(nextChar != 0) // Don't try delete char, which is not exists.
{
nextChar--;
lcd.setCursor(4 + nextChar,1);
lcd.print(" ");
lcd.setCursor(4 + nextChar,1);
}
}
else
{
lcd.print(changePassKeyPressed);
currentPassword[nextChar] = changePassKeyPressed;
nextChar++;
}
}
else
{
if(changePassKeyPressed == 'D')
{
break;
}
if(changePassKeyPressed == '#')
{
return false;
}
if(changePassKeyPressed == '*')
{
nextChar--;
}
}
}
return true;
}
Delete a single character you have here...
else if(changePassKeyPressed=='*')
{
if(nextChar != 0) // Don't try delete char, which is not exists.
{
nextChar--;
lcd.setCursor(4 + nextChar,1);
lcd.print(" ");
lcd.setCursor(4 + nextChar,1);
}
}
When you enable the cursor in the lcd display lcd.blink(), it visually looks like it is actually deleting a character, and in fact you replaced the last character with a space.

Assigning address to NULL pointer using malloc is making program freeze? This is probably quite basic?

Here is my code for a texas old 'em poker program:
I have tried debugging this for hours and have looked everywhere! I probably have some very fundamental flaw in my knowledge of pointers and using malloc but I have no idea why this happens:
The program compiles fine and runs fine until it reaches the malloc function trying to assign a memory address to the cards variable cards *individualhand. The printf if statement just before confirms it is a NULL pointer and can be assigned.
Also included are a couple of the other functions. The functions printhand (prints the poker hand and islegal (detects illegal card inputs) I have omitted.
This might be a lot of code at once but I have a feeling that the answer is pretty simple
The error occurs in the handget function about half way down the code:
int hander(cards **handPtr,int counter) {
int i, nr_of_cards = 2;
char rawsuit, rawcard[4];
if(counter==0){
// allocate the required amount of memory for your cards
(*handPtr) = (cards *) malloc(nr_of_cards * sizeof(cards));
}
// ask for the cards
for (i=0; i<nr_of_cards; i++) do {
scanf("%3s", &rawcard);
rawsuit = rawcard[0];
if (rawcard[1]=='1') {
if (rawcard[2]=='0') {
(*handPtr)[i].value = ten;
} else {
(*handPtr)[i].value = zero;
}
} else if (rawcard[1]=='2') {
(*handPtr)[i].value = two;
} else if (rawcard[1]=='3') {
(*handPtr)[i].value = three;
} else if (rawcard[1]=='4') {
(*handPtr)[i].value = four;
} else if (rawcard[1]=='5') {
(*handPtr)[i].value = five;
} else if (rawcard[1]=='6') {
(*handPtr)[i].value = six;
} else if (rawcard[1]=='7') {
(*handPtr)[i].value = seven;
} else if (rawcard[1]=='8') {
(*handPtr)[i].value = eight;
} else if (rawcard[1]=='9') {
(*handPtr)[i].value = nine;
} else if (rawcard[1]=='J') {
(*handPtr)[i].value = jack;
} else if (rawcard[1]=='Q') {
(*handPtr)[i].value = queen;
} else if (rawcard[1]=='K') {
(*handPtr)[i].value = king;
} else if (rawcard[1]=='A') {
(*handPtr)[i].value = ace;
} else {
(*handPtr)[i].value = zero;
}
switch (rawsuit) {
case 'h':
(*handPtr)[i].suit = hearts;
break;
case 'd':
(*handPtr)[i].suit = diamonds;
break;
case 'c':
(*handPtr)[i].suit = clubs;
break;
case 's':
(*handPtr)[i].suit = spades;
break;
default:
(*handPtr)[i].value = zero;
}
} while (!islegal(*handPtr, i+1));
return nr_of_cards;
}
int handget(cards **playerhand,cards *thishands, int handsize) {
cards *player,*individualhand=NULL;
int i,playerhandsize=2,j=0,nr_players,phandsize,counter=0, individualhandsize;
printf("Please enter the number of players: ");
scanf("%d",&nr_players);
(*playerhand) = (cards *) malloc(((playerhandsize*nr_players)*sizeof(cards))+(handsize*sizeof(cards)));
handcat(playerhand,thishands,handsize);
for (i=1;i<=nr_players;i++){
do {
printf("Please enter the cards for player %d: ",i);
phandsize = (i*hander(&player,counter))+handsize;
playerflopcat(playerhand,player,j,phandsize,handsize);
counter++;
} while (!islegal(*playerhand, phandsize));
j++;
}
printf("The cards on the table are:\n");
printhand(thishands,handsize);
for (i=1;i<=nr_players;i++){
printf("The private cards of player %d are ",i);
printhand(*playerhand+(handsize+(2*(i-1))),2);
}
for (i=1;i<=nr_players;i++){
individualhandsize = handsize + playerhandsize;
printf("individualhandsize=%i\n",individualhandsize);
if(individualhand==NULL){
printf("individualhand EQUALS NULL!");
}
individualhand=((cards *) malloc(individualhandsize*sizeof(cards)));//THIS IS WHERE IT ALL GOES WRONG!!
printf("made it this far chaps!!\n");
memcpy(individualhand,playerhand,individualhandsize*sizeof(cards));
printf("made it this far chaps!!\n");
printf("The cards available to player %d are ",i);
/*i have yet to add code here*/
}
return nr_players;
}
void handcat(cards **playerhand,cards *playerx, int nr_cards){
memcpy(*playerhand,playerx,nr_cards*sizeof(cards));
return;
}
void playerflopcat(cards **playerhand,cards *playerx,int j, int nr_cards,int handsize){
memcpy((*playerhand+(handsize+(2*j))),playerx,nr_cards*sizeof(cards));
return;
}
The method I am using to call function handget:
int main(void) {
int handsize=0, playerhandsize=0, nr_of_players=0;
cards *thishand, *playerhands;
handsize = flop(&thishand);
//flop asks user for list of cards
//user inputs(e.g. "d5 d6 d7 d8 d9")
//flop returns int handsize=5
printhand(thishand,handsize);
//printhand returns a list (of handsize length) of the cards making up thishand
//e.g. "d5 d6 d7 d8 d9"
nr_of_players = handget(&playerhands,thishand,handsize);
//handget is the function we're looking at
//takes thishand which was assigned (using function flop) to a space in memory containing list of cards ("d5 d6 d7 d8 d9")
//also uses int handsize = 5
//playerhands is assigned in function handget
// printhand(playerhands,(handsize+(nr_of_players*2)));
return 0;
}
Just for completeness' sake I have include function flop
int flop(cards **handPtr) {
int i,*q=NULL,n=NULL;
int j[5]={0,0,0,0,0};
int k[5]={1,1,1,1,1},nr_of_cards = 5;//for more/less cards CHANGE HERE!
char rawsuit, rawcard[4];
// allocate the required amount of memory for your cards
(*handPtr) = (cards *) malloc(nr_of_cards * sizeof(cards));
n=memcmp(j,k,sizeof(j));
while(n!=0) {
printf("Please input the five cards on the table: ");
q=rawtoflop(*handPtr,nr_of_cards);
for (i=0;i<nr_of_cards;i++) {
j[i]=*(q+i);
}
n=memcmp(j,k,sizeof(j));
}
return nr_of_cards;
}
The code for islegal:
int islegal(cards *hand, int nr_of_cards) {
int i, fulldeck[4][13]={0};
int current_value, current_suit;
cards *current_card = hand;
int legal = 1;
for (i=0; i<nr_of_cards; i++) {
current_value = (int) (*current_card).value;
current_suit = (*current_card).suit;
// if the current card has value zero, it is not a valid hand
if (current_value==0) {
legal = 0;
break;
}
//check if the current card already appears, if yes invalid hand, if no,
//change the flag for that card in the full deck.
//Since (two) will correspond to fulldeck[.][0] there is a -2 offset.
if ( (fulldeck[current_suit][current_value - 2]) > 0 ) {
legal = 0;
break;
} else {
fulldeck[current_suit][current_value - 2]++;
}
current_card++;
}
return legal;
}
You are calling the function handget as :
nr_of_players = handget(&playerhands,thishand,handsize);
That's fine, and it'll compile, because handget does in fact expect a cards **. However, you have never allocated space for a cards **.playerhands is still a cards* and taking its address and trying to allocate memory there may be why the malloc is failing.
Can you try running this by declaring cards ** playerhands instead of the card * that it currently is?

Resources