Teensy 4.1 and adafruit breakout ATWINC1500... parsing data issue

XRAD

Well-known member
I have this sketch working perfectly with adafruit feather M0 wifi ATWINC1500, but I want to use my teensy 4.1 for my project. I can connect to wifi and openweather.com with my API and 'GET' my data string using adafruit ATWINC1500 breakout...but I can't seem to parse it. I am using arduinojson 5.13.5 (yes, I know there is a newer '6' version..but ...this was working fine on the M0)

NO errors on compile or upload to teensy 4.1.....

any thoughts or pointers?

my arduino sketch:
Code:
#include "arduino_secrets.h" 
#include <WiFi101.h>
#include <ArduinoJson.h>//version=5.13.5!!! Not updated to version 6 yet

#define MOSI 11
#define MISO 12
#define SCK 13

char ssid[] = SECRET_SSID; //  your network SSID (name)
char pass[] = SECRET_PSW;//  your network PASSWORD ()

//open weather map api key(get the free version, takes a few hours before working)
String apiKey = SECRET_APIKEY;

//the city you want the weather for
String location = "canton,US";//use correct city,country code

int status = WL_IDLE_STATUS;
char server[] = "api.openweathermap.org";

WiFiClient client;

void setup() {
  //Configure pins for Adafruit ATWINC1500 Feather
  //using hardware mosi 11, miso 12, sck 13
  WiFi.setPins(8, 7, 4, 2);//(cs,irq, rst, enabl);
  // Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    // don't continue:
    while (true);
  }

  // attempt to connect to WiFi network:
  while ( status != WL_CONNECTED) {
    Serial.print("Attempting to connect to WPA SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network:
    status = WiFi.begin(ssid, pass);

    // wait 5 seconds for connection:
    delay(5000);
  }

  // you're connected now, so print out the data:
  Serial.println("You're connected to the network");
  //show some info
  printCurrentNet();
  printWifiData(); 
}


void loop() {
  getCurrentWeather();
  delay(5000);
  getWeatherForcast();
  delay(5000);
}


void getCurrentWeather() {
  Serial.println("\nStarting connection to server...");
  // if you get a connection, report back via serial:
  if (client.connect(server, 80)) {
    Serial.println("connected to server");
    // Make a HTTP request:
    client.print("GET /data/2.5/weather?");//current
    //client.print("GET /data/2.5/forecast?");//future
    client.print("q=" + location);
    client.print("&appid=" + apiKey);
    client.print("&cnt=1");//just for current forecast
    //client.print("&cnt=3");//forcast x3 ahead
    client.println("&units=imperial");
    client.println("Host: api.openweathermap.org");
    client.println("Connection: close");
    client.println();
  } else {
    Serial.println("unable to connect");
  }
  delay(1000);

  String line = "";

  while (client.connected()) {
    line = client.readStringUntil('\n');

    Serial.println(line);
    Serial.println("parsingValues");
    //create a json buffer where to store the json data
    StaticJsonBuffer<5000> jsonBuffer;
    JsonObject& root = jsonBuffer.parseObject(line);
    if (!root.success()) {
      Serial.println("parseObject() failed");
      return;
    }
    //get the data from the json tree
    String currentWeather = root["weather"][0]["main"];
    float visNow = root["visibility"];
    float tempNow = root["main"]["temp"];
    float pressNow = root["main"]["pressure"];
    float humNow = root["main"]["humidity"];
    float windNow = root["wind"]["speed"];
    String myCity = root["name"];

    Serial.println(currentWeather);
    Serial.print("Vis: ");
    Serial.println(visNow);
    Serial.print("Temp: ");
    Serial.println(tempNow);
    Serial.print("Press: ");
    Serial.println(pressNow);
    Serial.print("Humidity: ");
    Serial.println(humNow);
    Serial.print("Wind Speed: ");
    Serial.println(windNow);
    Serial.print("Location: ");
    Serial.println(myCity);

    //jsonBuffer.clear();//not needed
  }
}


void getWeatherForcast() {
  Serial.println("\nStarting connection to server...");
  // if you get a connection, report back via serial:
  if (client.connect(server, 80)) {
    Serial.println("connected to server");
    // Make a HTTP request:
    client.print("GET /data/2.5/forecast?");
    client.print("q=" + location);
    client.print("&appid=" + apiKey);
    client.print("&cnt=3");
    client.println("&units=metric");
    client.println("Host: api.openweathermap.org");
    client.println("Connection: close");
    client.println();
  } else {
    Serial.println("unable to connect");
  }
  delay(1000);

  String line = "";

  delay(4000);

  while (client.connected()) {
    line = client.readStringUntil('\n');
    //Serial.println(line);
    Serial.println("parsingValues");
    //create a json buffer where to store the json data
    StaticJsonBuffer<5000> jsonBuffer;
    JsonObject& root = jsonBuffer.parseObject(line);
    if (!root.success()) {
      Serial.println("parseObject() failed");
      return;
    }
    //get the data from the json tree
    String nextWeatherTime0 = root["list"][0]["dt_txt"];
    String nextWeather0 = root["list"][0]["weather"][0]["main"];
    String nextWeatherTime1 = root["list"][1]["dt_txt"];
    String nextWeather1 = root["list"][1]["weather"][0]["main"];
    String nextWeatherTime2 = root["list"][2]["dt_txt"];
    String nextWeather2 = root["list"][2]["weather"][0]["main"];
    // Print values.
    Serial.println(nextWeatherTime0);
    Serial.println(nextWeather0);
    Serial.println(nextWeatherTime1);
    Serial.println(nextWeather1);
    Serial.println(nextWeatherTime2);
    Serial.println(nextWeather2);
  }
}


void printWifiData() {

  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address : ");
  Serial.println(ip);
  Serial.println(ip);

  // print your MAC address:
  byte mac[6];
  WiFi.macAddress(mac);
  Serial.print("MAC address : ");
  Serial.print(mac[5], HEX);
  Serial.print(" : ");
  Serial.print(mac[4], HEX);
  Serial.print(" : ");
  Serial.print(mac[3], HEX);
  Serial.print(" : ");
  Serial.print(mac[2], HEX);
  Serial.print(" : ");
  Serial.print(mac[1], HEX);
  Serial.print(" : ");
  Serial.println(mac[0], HEX);
}

void printCurrentNet() {

  // print the SSID of the network you're attached to:
  Serial.print("SSID : ");
  Serial.println(WiFi.SSID());

  // print the MAC address of the router you're attached to:
  byte bssid[6];
  WiFi.BSSID(bssid);
  Serial.print("BSSID : ");
  Serial.print(bssid[5], HEX);
  Serial.print(" : ");
  Serial.print(bssid[4], HEX);
  Serial.print(" : ");
  Serial.print(bssid[3], HEX);
  Serial.print(" : ");
  Serial.print(bssid[2], HEX);
  Serial.print(" : ");
  Serial.print(bssid[1], HEX);
  Serial.print(" : ");
  Serial.println(bssid[0], HEX);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI) : ");
  Serial.println(rssi);

  // print the encryption type:
  byte encryption = WiFi.encryptionType();
  Serial.print("Encryption Type : ");
  Serial.println(encryption, HEX);
  Serial.println();
}
 
Last edited:
i guess i found two issues.

1st: I'm am NOT getting a good reply to my call (missing lots of data)using teensy 4.1, and reply is different than with the M0

so on teensy call, I GET this reply for current weather:
{"coord":{"lon":-83.4822,"lat":42.3087},"weather":[{"id":803,"main":"Clouds","description":"broken clouds","icon":"04d"}

while with M0 call, I GET this reply for current weather:
{"coord":{"lon":-83.4822,"lat":42.3087},"weather":[{"id":804,"main":"Clouds","description":"overcast clouds","icon":"04d"}],"base":"stations","main":{"temp":56.97,"feels_like":55.8,"temp_min":54.77,"temp_max":58.78,"pressure":1012,"humidity":73},"visibility":10000,"wind":{"speed":11.99,"deg":258,"gust":15.01},"clouds":{"all":100},"dt":1650919657,"sys":{"type":2,"id":2004926,"country":"US","sunrise":1650883049,"sunset":1650932757},"timezone":-14400,"id":4987990,"name":"Canton","cod":200}



2nd: not parsing the data I do get correctly...
 
2nd: not parsing the data I do get correctly...
I am confused by your last statement.
Are you saying it is fine if you don't attempt to parse the data?
If that is so then the problem is with parsing the data.
 
I was able to get your sketch running with a T4.0 connected to adafruit WINC1500.
Code:
Starting weather connection to server...
connected to server
{"coord":{"lon":-83.4822,"lat":42.3087},"weather":[{"id":804,"main":"Clouds","description":"overcast clouds","icon":"04d"}],"base":"stations","main":{"temp":43.83,"feels_like":36.43,"temp_min":41.99,"temp_max":47.03,"pressure":1020,"humidity":68},"visibility":10000,"wind":{"speed":16.11,"deg":250},"clouds":{"all":100},"dt":1651007499,"sys":{"type":2,"id":2004926,"country":"US","sunrise":1650969362,"sunset":1651019225},"timezone":-14400,"id":4987990,"name":"Canton","cod":200}
parsingValues
Clouds
Vis: 10000.00
Temp: 43.83
Press: 1020.00
Humidity: 68.00
Wind Speed: 16.11
Location: Canton

Starting forecast connection to server...
connected to server
disconnected
{"cod":"200","message":0,"cnt":3,"list":[{"dt":1651017600,"main":{"temp":5.87,"feels_like":1.7,"temp_min":4.39,"temp_max":5.87,"pressure":1021,"sea_level":1021,"grnd_level":997,"humidity":66,"temp_kf":1.48},"weather":[{"id":500,"main":"Rain","description":"light rain","icon":"10d"}],"clouds":{"all":100},"wind":{"speed":6.79,"deg":289,"gust":10.48},"visibility":10000,"pop":0.28,"rain":{"3h":0.11},"sys":{"pod":"d"},"dt_txt":"2022-04-27 00:00:00"},{"dt":1651028400,"main":{"temp":3.48,"feels_like":-0.67,"temp_min":1.92,"temp_max":3.48,"pressure":1022,"sea_level":1022,"grnd_level":998,"humidity":68,"temp_kf":1.56},"weather":[{"id":802,"main":"Clouds","description":"scattered clouds","icon":"03n"}],"clouds":{"all":40},"wind":{"speed":5.21,"deg":281,"gust":10.87},"visibility":10000,"pop":0,"sys":{"pod":"n"},"dt_txt":"2022-04-27 03:00:00"},{"dt":1651039200,"main":{"temp":0.1,"feels_like":-4.68,"temp_min":0.1,"temp_max":0.1,"pressure":1024,"sea_level":1024,"grnd_level":998,"humidity":72,"temp_kf":0},"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}],"clouds":{"all":9},"wind":{"speed":4.81,"deg":284,"gust":11.21},"visibility":10000,"pop":0,"sys":{"pod":"n"},"dt_txt":"2022-04-27 06:00:00"}],"city":{"id":4987990,"name":"Canton","coord":{"lat":42.3087,"lon":-83.4822},"country":"US","population":86825,"timezone":-14400,"sunrise":1650969362,"sunset":1651019225}}
parsingValues
2022-04-27 00:00:00
Rain
2022-04-27 03:00:00
Clouds
2022-04-27 06:00:00
Clear

I got rid of the readStringUntil() logic and replaced with
Code:
while (client.connected()) {
    if (client.available() ) {
      char c = client.read();
      line += c; 
    }
}
 Serial.println("disconnected");
 Serial.println(line); 
 Serial.println("parsingValues");
...
ArduinoJson (v5) parsing is working.
 
Last edited:
Hi Manitou! thank you for reply. I followed your instruction but on the T4.1, I am still getting:


You're connected to the network

Starting connection to server...
connected to server

current:
parsingValues
parseObject() failed

hmmmmmm....

Do you have a T4.1 to try my code on?

Did my original code work on the 4.0?

both have the ARM Cortex-M7....strange...

and I have run other code including TFT displays and GPS tracker without issues on my 4.1...
 
Never Mind! All good now. THX Manitou, your code snippet worked fine. I just had a '}' in the wrong spot, which I think made my code save only a partial string to the buffer.

Thanks Again! Now I will try to find out why your logic worked and readStringUntil('\n') does not.....
 
Never Mind! All good now. THX Manitou, your code snippet worked fine. I just had a '}' in the wrong spot, which I think made my code save only a partial string to the buffer.

Thanks Again! Now I will try to find out why your logic worked and readStringUntil('\n') does not.....

I'm not sure why readStringUntil('\n') worked for you. Looking at packets from the weatherserver, there is no \n in the reply TCP packet, just the json string (last character is } ). Maybe semantics of adafruit lib differs from teensy lib.

update to ArduinoJson v6
Code:
  //create a json buffer where to store the json data
  StaticJsonDocument<5000> root;
  DeserializationError error = deserializeJson(root, line);
  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.f_str());
    return;
  }
 
Last edited:
Re: readStringUntil()

The teensy Stream library has a 2nd argument for readStringUntil(), see hardware/teensy/avr/cores/teensy4/Stream.h
Code:
String readStringUntil(char terminator, size_t max = 120);
So the default max string length is 120 which explains the truncated json reply you were seeing. The json reply from the weather server is nearly 800 bytes, so you could try
readStringUntil('\n', 1000)
But as noted, using readStringUntil('\n') is faulty logic as the json reply does not have a '\n'
 
I tried a few other things like changing client timeout and string terminators and length. I wonder why teensy (Stream) readStringUntil only has a length of 120? seems odd...doubt it's a memory issue...maybe left over from older Stream arduino processor requirements? . I read through some of the wifi101 arduino files as well. Also tried some other ways to read(). But your tips got this working, so I am happy here. Now to add some GPS code to the teensy. I also pruned down the needed buffer memory for the string to just exceed required byte count. THX Manitou
 
I wonder why teensy (Stream) readStringUntil only has a length of 120? seems odd...doubt it's a memory issue...maybe left over from older Stream arduino processor requirements?

LECTURE ON:
Using unbounded string operations results in hard-to-debug programs and programs subject to hacker exploitation. So having a max size value is the more desirable API. Kudos to Teensy.
LECTURE OFF:

However using readStringUntil('\n', 1000) on the Adafruit M0 will give a compiler error

I also pruned down the needed buffer memory for the string to just exceed required byte count.
ArduinoJson has a tool for calculating memory size needed for json buffers given json input.
weather forecast json string: 1395 bytes, recommended buffer size: 3072 bytes
 
Last edited:
Yes, I have tried out that tool, really cool! TY for the string education!

3072 works for both the CURRENT and FORECAST strings buffers...3000 does not....That seems pretty close.....so I left it at 4000...I knowwwwwwwwww......lol....

why? in case openweather changes its reply length...maybe?
 
Back
Top