Arduino - unable to connect to wifi - string

I have this (partial) code, that is used to read the ssid and password from a text file on a SD card.
This data should then be used to connect to the local wifi. But it is unable to connect, and keeps saying "Establishing connection to WiFi..."
I also dont seem to be able to print what I have read from the SD card. Previously my readline function returned a string. That I was able to print properly and verified that the file is read as expected. Then, since wifi requires a Char* I changed the code to Char* and since then it didnt work anymore:
#include <SD.h>
#include <AccelStepper.h>
#include <MultiStepper.h>
#include <WiFi.h>
File myFile;
char* ssid;
char* password;
void setup() {
// put your setup code here, to run once:
pinMode(thetaPos, INPUT);
pinMode(rhoPos, INPUT);
Serial.begin(115200);
Serial.print("Initializing SD card...");
if (!SD.begin()) {
Serial.println("initialization failed!");
while (1);
}
Serial.println("initialization done.");
myFile = SD.open("/config.txt");
if (myFile) {
// read from the file until there's nothing else in it:
ssid = readLine();
password = readLine();
Serial.println(ssid);
Serial.println(password);
connectToNetwork();
// close the file:
myFile.close();
} else {
// file didn't open
}
}
void loop() {
}
char* readLine() {
char* received = "";
char ch;
while (myFile.available()) {
ch = myFile.read();
if (ch == '\n') {
return received;
} else {
received += ch;
}
}
return received;
}
void connectToNetwork() {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Establishing connection to WiFi..");
}
Serial.println("Connected to network");
}
what am I doing wrong?
this is the serial output:
Initializing SD card...initialization done.
ore calibration nvs commit failed(0x%x)
wdt_config->intr_handle)
Establishing connection to WiFi..
Establishing connection to WiFi..
Establishing connection to WiFi..
Establishing connection to WiFi..

Well, where is the error? This won't work as you hope:
char* readLine() {
char* received = ""; // poiner to \0 somewhere...
char ch;
while (myFile.available()) {
ch = myFile.read();
if (ch == '\n') {
return received;
} else {
received += ch; // move pointer to location ch bytes after...
}
}
return received;
}
You are utilizing pointer arithmetic - you are moving pointer around the memory and you are not storing anything anywhere. It's not String class that overloads += char and allows you to concatenate character to the end of it.
Basically you can use:
String readLine() {
String received;
while (myFile.available()) {
ch = myFile.read();
if (ch == '\n') {
return received;
} else {
received += ch;
}
}
return received;
}
and it'll work (althrough it's not a good idea to append character by character to the String - heap memory gets fragmented really fast by this approach)
To avoid other mistakes, usage is something like:
String ssid = readLine();
String pass = readLine();
Wifi.begin(ssid.c_str(), pass.c_str());
//// definitely do not do something like:
// Wifi.begin(readLine().c_str(), readLine().c_str()); // !!! WRONG !!!
//// as the order of executing parameters isn't specified (and in the GCC it's from the last to the first)

Related

Why does the string output from Arduino look like alien text?

I'm trying to set up a serial communication between Arduino and MATLAB over USB. I have this basic code where I'm sending "hello" from MATLAB to Arduino, and I read it back and print it in MATLAB. However, the "hello" sent from Arduino looks like a strange text.
Arduino:
void setup() {
Serial.begin(57600);
Serial.println("ready");
}
void loop() {
String input;
if (Serial.available()) {
char c = Serial.read();
while (c != '\n') {
input += c;
c = Serial.read();
}
Serial.println("I received: " + String(input));
input = "";
}
}
MATLAB:
s = serial('COM3');
set(s, 'BaudRate', 57600);
fopen(s);
pause(1);
first = strtrim(convertCharsToStrings(fgetl(s)));
if first == "ready"
fprintf(s, '%s', 'hello\n');
for i = 1:10
tline = strtrim(convertCharsToStrings(fgetl(s)));
disp(tline);
if size(tline, 2) > 0
fprintf(s, '%s', 'hello\n');
end
end
end
fclose(s);
The output in MATLAB looks like this:
I received: hÿÿÿÿÿÿeÿÿÿÿÿÿÿlÿÿÿÿÿÿÿÿlÿÿÿÿÿÿoÿÿÿÿÿÿÿ
Also, I would appreciate any constructive criticism on improving my code for serial communication. This is my first time, and I'm trying to get a simple setup in which Arduino and MATLAB take turns writing and reading. Thank you.
Your microcontroller code reads faster than you're physically sending characters, so you're reading from an empty buffer. Serial.available() has one char for you, you read it, then you read more chars even though the receive buffer is already empty. Serial.read() will return -1 when there's nothing to read. -1 cast to char is 0xFF, or in Ascii 'ÿ'.
You could change loop() to something like
void loop() {
String input;
while (Serial.available()) {
char c = Serial.read();
if (c != '\n') {
input += c;
} else {
Serial.println("I received: " + String(input));
input = "";
}
}
}
Or you could go with Arduino's Serial.readString():
void setup() {
Serial.begin(57600);
Serial.setTimeout(20);
Serial.println("ready");
}
void loop() {
String input = Serial.readString();
Serial.println("I received: " + input);
}
Both untested, but you get the idea.

Weird shapes as output( Strings)- C language

So i have a problem. I have to separate the first name, last name and hostname of email.
For example:
zephyr.extreme#gmail.com>> Input
Output=
First name= Zephyr
Last name= extreme
Host Name= gmail.com
I am not getting the desired result. I am getting some weird shapes as output.
Code:
#include <stdio.h>
int main()
{
char email[40], first[20],last[20],host[30];
printf("Enter the email= ");
gets(email);
int i;
while(email[i]!='\0')
{
while(email[i]!='.')
{
first[i]=email[i];
i++;
}
while(email[i]!='#')
{
last[i]=email[i];
i++;
}
while(email[i]!='\0')
{
host[i]=email[i];
i++;
}
}
puts(first);
puts(last);
puts(host);
}
Assuming the format will always be first.last#host..., use this code:
#include <stdio.h>
#include <string.h>
int main()
{
char email[40], first[20],last[20],host[30],name[40];
int firstDot,atSymbol;
int i;
int length;
char *token;
printf("Enter the email= ");
gets(email);
length = strlen(email);
for(i=0;i<length;i++){
if(email[i]=='.')
{
firstDot = i;
}
else if(email[i]=='#')
{
atSymbol = i;
}
}
strncpy(name,email,atSymbol);
name[atSymbol]= '\0';
token = strtok(name, ".");
/* walk through other tokens */
while( token != NULL )
{
printf( "%s\n", token );
token = strtok(NULL, ".");
}
strncpy(host,email+atSymbol,length-atSymbol);
host[length-atSymbol] = '\0';
puts(host);
}
So i updated the code, now the only problem is the last output.
After host name= gmail.com prints, but then some extra shapes are also printing. These are smile face and some weird symbols.
Code:
#include <stdio.h>
int main()
{
char email[40], first[20],last[20],host[30];
printf("Enter the email= ");
gets(email);
int i=0,j;
while(email[i]!='.')
{
first[i]=email[i];
i++;
}
i=0;
while(email[i]!='#')
{
last[i]=email[i];
i++;
}
j=i;
i=0;
while(email[j]!='\0')
{
host[i]=email[j];
j++;
i++;
}
printf("First Name= ");
puts(first);
printf("Last name= ");
puts(last);
printf("Host name= ");
puts(host);
}
C strings (char pointers) should be null-terminated. This means your string needs a '\0' character at its end so that string manipulation functions such as puts or strlen know where they end, in constrast to other languages where the string's length is stored together with it. The "weird shapes" you are seeing are just random data stored after the end of the string being interpreted as characters. When you call puts it just keeps outputting bytes-as-characters until it randomly finds a byte with value '\0'
You can solve this by adding a '\0' character to the end of the string after each of the blocks where you write a string.
while(email[i]!='.')
{
first[i]=email[i];
i++;
}
email[i] = '\0'; //same thing as email[i] = 0; but using a char makes what
//you're doing clearer

String converted when I send it in a structure with RF24 library

I'm sending a data struct with the RF24 library from one node to another. This structure contains two string and one float.
When I send the structure with the transmitter and I print it to the serial output I get this:
El sensor PIR situat en Menjador te el valor 1.00
I see this in the receiver when I print it to the serial output:
El sensor œ>U situat en Üߧŋ>r te el valor 1.00
Why are the two String changed ("PIR" and "Menjador")?
The structure is this:
struct sensorData {
String sensorType;
String sensorLocation;
float sensorValue;
} PIR1, sensor;
This is how I write it to the radio:
radio.write( &PIR1, sizeof(PIR1) ));
This is how I read it from the radio:
radio.read( &sensor, sizeof(sensor));
And this is how I print it to the serial output in the receiver:
void printOutData(sensorData* data) {
Serial.print("El sensor ");
Serial.print(data->sensorType);
Serial.print(" situat en ");
Serial.print(data->sensorLocation);
Serial.print(" te el valor ");
Serial.println(data->sensorValue);
}
Thank you!!
The String type does not actually contain the bytes of the sensor type and location; it points to the bytes. You are bascially sending the memory address of those bytes, not the bytes themselves.
You need to change your data structure so that it can contain the bytes inside the structure, with "C strings" aka "char arrays":
static const uint8_t SENSOR_TYPE_SIZE = 4;
static const uint8_t SENSOR_LOC_SIZE = 12;
struct sensorData {
char sensorType[ SENSOR_TYPE_SIZE ];
char sensorLocation[ SENSOR_LOC_SIZE ];
float sensorValue;
} PIR1, sensor;
Of course, you will have to change how you set those member values. Without your complete sketch, I can only offer a few possibilities:
void setup()
{
Serial.begin( 9600 );
// Set to a constant value (i.e., a double-quoted string literal)
strncpy( PIR1.sensorType, "TMP", sizeof(PIR.sensorType)-1 );
PIR1.sensorType[ sizeof(PIR.sensorType)-1 ] = '\0'; // NUL-terminate
// Set to characters received over Serial, up to size-1 chars *or* a newline
// (This blocks until the line is entered! Nothing else will happen
// until the line has been completely received.)
size_t count = Serial.readBytesUntil( '\n', PIR1.sensorType, sizeof(PIR.sensorType)-1 );
PIR.sensorType[ count ] = '\0'; // NUL-terminate
}
void loop()
{
// Non-blocking receive of a line. Other things can be performed
// while we're waiting for the newline to arrive.
if (Serial.available()) {
// A char finally came in!
char c = Serial.read();
// end-of-line?
if (c == '\n') {
// Pressed ENTER, send what we have now
PIR.sensorLocation[ count ] = '\0'; // NUL-terminate the C string
radio.write( &PIR1, sizeof(PIR1) ));
// Reset for next time
count = 0;
} else { // not end-of-line, save another char (if there's room)
if (count < sizeof(PIR.sensorLocation)-1) {
PIR.sensorLocation[ count++ ] = c;
}
}
}
// Do some other things here... maybe check some buttons?
}
There are many reasons to avoid String, so switching to char arrays will actually pay off in the long run.

Http get request using Arduino and Azure mobile services

I have hooked up my arduino with Azure mobile services and http post request is working fine where I am able to send data from sensor. But when using a http get request to access data from the tables, I am landing up with this data whereas I should be getting a json data in the Serial Window.
X-cache-Lookup: MISS from Webmaster:8080
Here is the code that is on my Arduino. I have no idea where I am wrong.
#include <ArduinoJson.h>
#include <SPI.h>
#include <Ethernet.h>
#define RESPONSE_JSON_DATA_LINENNO 10
// Ethernet shield MAC address (sticker in the back)
byte mac[] = { 0xA4, 0x5D, 0x36, 0x6A, 0xE1, 0xE1 };
int qq=0;
const char* server= "avirup.azure-mobile.net";
const char* table_name= "iottest";
const char* ams_key="rkIEUqVlFrgtmqNeMmaamgUQywwMjE42";
char stat;
EthernetClient client;
char fin='0';
char buffer[64];
int charIndex=0;
StaticJsonBuffer<200> jsonbuffer;
void send_request()
{
Serial.println("\nconnecting...");
if (client.connect(server, 80)) {
Serial.print("sending ");
// GET URI
sprintf(buffer, "GET /tables/%s HTTP/1.1", table_name);
Serial.println(buffer);
client.println(buffer);
// Host header
sprintf(buffer, "Host: %s", server);
client.println(buffer);
// Azure Mobile Services application key
sprintf(buffer, "X-ZUMO-APPLICATION: %s", ams_key);
client.println(buffer);
// JSON content type
client.println("Content-Type: application/json");
//POST body
sprintf(buffer, "", "");
//Content length
client.print("Content-Length: ");
client.println(strlen(buffer));
Serial.print("Content length: ");
Serial.println(strlen(buffer));
// End of headers
client.println();
// Request body
client.println(buffer);
}
else {
Serial.
println("connection failed");
}
}
/*
** Wait for response
*/
void wait_response()
{
while (!client.available()) {
if (!client.connected()) {
return;
}
}
}
/*
** Read the response and dump to serial
*/
// Read the response and dump to serial
void read_response()
{
int jsonStringLength;
int jsonBufferCntr=0;
int numline=RESPONSE_JSON_DATA_LINENNO;
//Ignore the response except for the 10th line
while (client.available()) {
char c = client.read();
if (c == '\n')
{
numline -=1;
}
else
{
if (numline == 0 )
{
//Capture the 10th line in the response
//To do: Could be more deterministic about this:
// Expect certain content, checks and balances etc.
buffer[jsonBufferCntr++] = c;
buffer[jsonBufferCntr] = '\0';
}
}
}
Serial.println("Received:");
Serial.println(buffer);
Serial.println("");
}
/*
** Close the connection
*/
void parse()
{
//char json[] = "{\"id\":\"34CCC60D-15D2-4B53-AB8E-FF3745FDC945\",\"control\":1}";
JsonObject& root = jsonbuffer.parseObject(buffer);
if(!root.success())
{
Serial.println("PARSING FAILED!!!");
return;
}
//fin= root["control"][0];
int f= root["control"][0];
Serial.println("Decoded: ");
Serial.println(f);
}
void end_request()
{
client.stop();
}
/*
** Arduino Setup
*/
void setup()
{
pinMode(13,OUTPUT);
digitalWrite(13,LOW);
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect.
}
if (Ethernet.begin(mac) == 0) {
Serial.println("ethernet failed");
for (;;) ;
}
// give the Ethernet shield a second to initialize:
delay(1000);
}
/*
** Arduino Loop
*/
void loop()
{
send_request();
wait_response();
read_response();
end_request();
delay(1000);
}

Echo Serial Strings with Arduino

EDIT 2: I got the solution. Anytime someone wants the code I'd be happy to provide. Peace.
Topic:
I'm trying an experiment of echoing strings that I receive in my arduino.
So this is the code so far:
byte byteRead = 0;
bool readable = LOW;
char fullString[50];
int index = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
// State 1
if (Serial.available()) {
readable = HIGH; // flag to enter in the next state when there's nothing else to read
byteRead = Serial.read();
fullString[index] = (char)byteRead;
index++;
}
// State 2
if (readable == HIGH && !Serial.available()){
fullString[index] = '\0'; // '\0' to terminate the string
Serial.println(fullString);
// resets variables
index = 0;
readable = LOW;
}
/**
* Somehow a delay prevents characters of the string from having
* a line printed between them.
* Anyways, when the string is too long, a line is printed between
* the first and second characters
*/
delay(5);
}
Somehow this delay in the end prevents the characters of the string from having a line printed between them, like this:
H
e
l
l
o
Nonetheless, when the string is too long, a line is printed between the first and second characters.
Do you know a better way of doing this?
EDIT: Next time I'd appreciate answers from someone who actually KNOWS programming. Not just condescending idiots.
that's my String Echo
#define MAX_BUFFER_SIZE 0xFF
char buffer[MAX_BUFFER_SIZE];
void setup() {
Serial.begin(115200);
buffer[0] = '\0';
}
void loop() {
while (Serial.available() > 0) {
char incomingByte;
size_t i = 0;
do {
incomingByte = Serial.read();
buffer[i++] = incomingByte;
} while (incomingByte != '\0' && i < MAX_BUFFER_SIZE);
if(i > 0){
delay(1000); /// delay for the echo
Serial.write(buffer, i);
}
}
}
You want to echo the string read, so just echo the input.
void setup() {
Serial.begin(9600);
}
void loop() {
int c = Serial.read();
if (c >= 0) Serial.write(c);
}

Resources