How to write the code to display JSON data onto an OLED

  • Thread starter Deleted member 750607
  • Start date

Thread Starter

Deleted member 750607

Joined Dec 31, 1969
0
I started by kind of slapping together the code I had learned to display text on my little OLED, with the code that ive been using to get single readings from a website/JSON to track the longitude and latitude of the International Space Station.

Apparently this approach does not work.....:oops:

Can anyone walk me through the protocol for this type of project? not finding what im looking for online...so far...
Here's the code that I threw together, and im not surprised it doesn't work, but maybe it will help you see where im at...

Main file:
#include <Adafruit_EEPROM_I2C.h>
#include <Adafruit_FRAM_I2C.h>

#include <Adafruit_SSD1306.h>
#include <splash.h>
#include <Wire.h>
#include <WiFi.h>
#include <WiFiUdp.h>
#include <WiFiClient.h>
#include <WiFiServer.h>

#include "USE_ESP8266.h"
#include <TimeLib.h>
char server [] = "api.open-notify.org";
void digitalClockDisplay();

#include <Adafruit_SSD1306.h>
#include <splash.h>
#include <Adafruit_GrayOLED.h>
#include <gfxfont.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <SPI.h>
#include <Wire.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C

Adafruit_SSD1306 display;

#define OLED_RESET -1
Adafruit_SSD1306 display(OLED_RESET);

void setup ()
{
Serial.begin (9600);
Wire.begin ();
display.begin (0x3C);
 
  Serial.begin(115200);
  if (!configureNetwork()) //start the network
  {
    Serial.println("Failed to configure the network");
    while(1)
    {
      delay(0); //halt; ESP8266 does not like infinity loop without a delay
    }
   }
int ret = client.connect(server, 80);
if (ret == 1)
{
  Serial.println("Connected");
  client.println("GET /iss-now.json HTTP/1.0"); //the http request
  client.print("Host: "); client.println(server);
  client.println("Connection: close");
  client.println();
}
else
{
  Serial.println("Connection failed, error was: ");
  Serial.print(ret, DEC);
  while(1)
  {
    delay(0); //halt; esp8266 does not like infinite loop without a delay
 
  }
 }
}

char timestampMarker[] = "\"timestamp\":";
char posMarker[] = "\"iss_position\":";

void loop ()
{
  if (client.available())
  {
    String id = client.readStringUntil('"');
    if (id.equals("timestamp")) //start of timestamp
    {
      if (client.find(':')) //a ":" follows each identifier
      {
      unsigned long timestamp = client.parseInt();
      setTime(timestamp);
      digitalClockDisplay();
      
      }
      else
      {
        Serial.println("failed to parse timestamp.");
      }
    }
    if (id.equals("iss_position")) //start of position data
    {
      if (client.find(':')) 
      {
       while(client.peek () != '}' && client.find('"'))
       {
        String id = client.readStringUntil ('"');
        float val = client.parseFloat ();
        client.find ('"');
        Serial.print(id + ":"); Serial.println(val, 4);
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println(id + ":"); display.println(val, 4);
  display.display();
  delay (2000);
       }
      }
      else
      {
        Serial.print("Failed to parse position data.");
      }
    }
  }
if (!client.connected())
  {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
    while(1)
  {
    delay (0); //halt, esp8266 does not like loop w/o delay
  }
 }
}
String padDigits(int digit)
{
  String str = String("0") + digit; //put a zero in front of digit
  return str.substring(str.length() - 2);
}

void digitalClockDisplay ()
{
  String datestr = String(year()) + "-" + padDigits(month()) +
                   "-" + padDigits(day());
  String timestr = String(hour()) + ":" + padDigits(minute()) +
                   ":" + padDigits(second());
  Serial.println(datestr + " " + timestr);
}

Header file:
#include <Adafruit_EEPROM_I2C.h>
#include <Adafruit_FRAM_I2C.h>

#include <Adafruit_SSD1306.h>
#include <splash.h>
#include <Wire.h>
#include <WiFi.h>
#include <WiFiUdp.h>
#include <WiFiClient.h>
#include <WiFiServer.h>
WiFiClient client;

#include <SPI.h>
#include <ESP8266WiFi.h>

const char ssid[] = "Home25";
const char password[] = "6033216098";

#include <Adafruit_SSD1306.h>
#include <splash.h>
#include <Adafruit_GrayOLED.h>
#include <gfxfont.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <SPI.h>
#include <Wire.h>

bool configureNetwork()
{
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay (1000);
    Serial.print("Waiting for connection to "); Serial.println(ssid);
  }
    return true;
  }
 

Thread Starter

Deleted member 750607

Joined Dec 31, 1969
0
I got the OLED to display the information, but its messed up, "longitude" and "Latitude" are on top of each other, as are the two coordinates themselves...anyone know how to help?
 

KeithWalker

Joined Jul 10, 2017
3,063
In your display statements you are not supplying the display with the x/y coordinates of where to display the messages, so they are all appearing in the 0/0 position on the display. You will need to detect which message you are displaying and give each a unique position to start on the display.
 

Thread Starter

Deleted member 750607

Joined Dec 31, 1969
0
In your display statements you are not supplying the display with the x/y coordinates of where to display the messages, so they are all appearing in the 0/0 position on the display. You will need to detect which message you are displaying and give each a unique position to start on the display.
no, I can't figure out how to isolate the values (long/lat) from the JSON ... (id + ":"), (val 4)
id + : is the name long or lat, and val 4 is the coordinate, but they are on top of each other no matter where I put them on the display...
both long and lat are on top of each other although they are all on the right spot on the OLED
 

Thread Starter

Deleted member 750607

Joined Dec 31, 1969
0
I am tracking the international space station, and am currently working on displaying that info on an OLED that can be updated.
I can't figure out how to isolate the values (long/lat) from the JSON ... (id + ":"), (val 4)

id + : is the name "long" or "lat", and val 4 is the value of the coordinate, but they are on top of each other no matter where I put them on the display...

both long and lat are on top of each other although they are all on the right spot on the OLED

MAIN FILE:
#include <Adafruit_SSD1306.h>
#include <splash.h>
#include <Adafruit_GrayOLED.h>
#include <gfxfont.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <SPI.h>
#include <Wire.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#include "USE_ESP8266.h"
#include <TimeLib.h>
char server [] = "api.open-notify.org";
void digitalClockDisplay();

void setup ()
{
display.begin(SSD1306_SWITCHCAPVCC, 0X3C);
display.clearDisplay ();

  Serial.begin(115200);
  if (!configureNetwork()) //start the network
  {
    Serial.println("Failed to configure the network");
    while(1)
    {
      delay(0); //halt; ESP8266 does not like infinity loop without a delay
    }
   }
int ret = client.connect(server, 80);
if (ret == 1)
{
  Serial.println("Connected");
  client.println("GET /iss-now.json HTTP/1.0"); //the http request
  client.print("Host: "); client.println(server);
  client.println("Connection: close");
  client.println();
}
else
{
  Serial.println("Connection failed, error was: ");
  Serial.print(ret, DEC);
  while(1)
  {
    delay(0); //halt; esp8266 does not like infinite loop without a delay
  }
}
}

char timestampMarker[] = "\"timestamp\":";
char posMarker[] = "\"iss_position\":";

void loop ()
{
  if (client.available())
  {
    String id = client.readStringUntil('"');
    if (id.equals("timestamp")) //start of timestamp
    {
      if (client.find(':')) //a ":" follows each identifier
      {
      unsigned long timestamp = client.parseInt();
      setTime(timestamp);
      digitalClockDisplay();
    
      }
      else
      {
        Serial.println("failed to parse timestamp.");
      }
    }
    if (id.equals("iss_position")) //start of position data
    {
      if (client.find(':'))
      {
       while(client.peek () != '}' && client.find('"'))
       {
        String id = client.readStringUntil ('"');
        float val = client.parseFloat ();
        client.find ('"');
        Serial.print(id + ":"); Serial.println(val, 4);

display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("longitude:");
display.display();

display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,10);
display.println(val, 1);
display.display();

display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,40);
display.println("latitude:");
display.display();


display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,50);
display.println(val, 2);
display.display();


       }
      }
      else
      {
        Serial.print("Failed to parse position data.");
      }
    }
  }
if (!client.connected())
  {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
    while(1)
  {
    delay (0); //halt, esp8266 does not like loop w/o delay
  }
}
}
String padDigits(int digit)
{
  String str = String("0") + digit; //put a zero in front of digit
  return str.substring(str.length() - 2);
}

void digitalClockDisplay ()
{
  String datestr = String(year()) + "-" + padDigits(month()) +
                   "-" + padDigits(day());
  String timestr = String(hour()) + ":" + padDigits(minute()) +
                   ":" + padDigits(second());
  Serial.println(datestr + " " + timestr);

}


HEADER FILE:
#include <SPI.h>
#include <ESP8266WiFi.h>
const char ssid[] = "Home25";
const char password[] = "6033216098";
WiFiClient client;

bool configureNetwork()
{
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay (1000);
    Serial.print("Waiting for connection to "); Serial.println(ssid);
  }
    return true;
  }
Screen Shot 2021-05-05 at 10.06.56 PM.png
 

Attachments

Last edited by a moderator:

click_here

Joined Sep 22, 2020
548
I'm guessing that "val" is a global variable?

Just for debugging, temporaraly change val to known set values that do not change and add a massive delay.

Does the problem stay, or go away?

Now get rid of the delay and try again
 

Thread Starter

Deleted member 750607

Joined Dec 31, 1969
0
I'm guessing that "val" is a global variable?

Just for debugging, temporaraly change val to known set values that do not change and add a massive delay.

Does the problem stay, or go away?

Now get rid of the delay and try again
yeah if I fill in a set value, that will show up fine...but it goes back to normal when I put VAL back in place
 

Thread Starter

Deleted member 750607

Joined Dec 31, 1969
0
I'm guessing that "val" is a global variable?

Just for debugging, temporaraly change val to known set values that do not change and add a massive delay.

Does the problem stay, or go away?

Now get rid of the delay and try again
im sorry I think I misunderstood what you said to do
 

click_here

Joined Sep 22, 2020
548
How is "val" getting updated between the two println?

At the very least shouldn't there be 2 seporate variables for the 2 different values?
 

Thread Starter

Deleted member 750607

Joined Dec 31, 1969
0
How is "val" getting updated between the two println?

At the very least shouldn't there be 2 seporate variables for the 2 different values?
yeah! but I got this code from a book, and it was only meant to display in the serial monitor....which it does perfectly, with long and lat separated, but not so when I upload to OLED

if you know how to make it into two, let me know, although im trying to change the original code as little as possible...
I could start over and make a new one I guess but, yeah...trying to just tweak what I already have
 

KeithWalker

Joined Jul 10, 2017
3,063
There is only one Serial.print statement to display the two values on the monitor.
What happens if you do the same for the display? comment out lines 102 to 113 and change line 99 to: display.println(val, 4);
Show us the result.
 

Thread Starter

Deleted member 750607

Joined Dec 31, 1969
0
There is only one Serial.print statement to display the two values on the monitor.
What happens if you do the same for the display? comment out lines 102 to 113 and change line 99 to: display.println(val, 4);
Show us the result.
when I do that all 4 lines of text are on top of each other
 

Thread Starter

Deleted member 750607

Joined Dec 31, 1969
0
There is only one Serial.print statement to display the two values on the monitor.
What happens if you do the same for the display? comment out lines 102 to 113 and change line 99 to: display.println(val, 4);
Show us the result.
actually the names long and lat are on top of each other and the number values are on top of each other
 

click_here

Joined Sep 22, 2020
548
Keith is asking what happens if you send that data to your computer instead of the OLED

JSON files are just a list of items and their values.

Long/lat would be seporate data items, right?

So are you getting one data (say long) and printing it for both long/lat, and then getting the value for lat, and then printing that for both long/lat

It would be toggling from one value to the other and appear that one value is over the other.

To see if you are doing this add a large delay at the end of the loop (say 1 sec) and see whats happening
 

Thread Starter

Deleted member 750607

Joined Dec 31, 1969
0
Keith is asking what happens if you send that data to your computer instead of the OLED

JSON files are just a list of items and their values.

Long/lat would be seporate data items, right?

So are you getting one data (say long) and printing it for both long/lat, and then getting the value for lat, and then printing that for both long/lat

It would be toggling from one value to the other and appear that one value is over the other.

To see if you are doing this add a large delay at the end of the loop (say 1 sec) and see whats happening
adding a 1 sec delay at the end didn't change anything
 

Thread Starter

Deleted member 750607

Joined Dec 31, 1969
0
adding a 1 sec delay at the end didn't change anything
the coordinates appear perfectly fine with their respective "id's" (long and lat) in the serial monitor, by the way...its only in the display that things go wrong
 

click_here

Joined Sep 22, 2020
548
>adding a 1 sec delay at the end didn't change anything

I'm guessing that you meant that it didn't pause as one value for the second, and then change to the other the next second, and then back to the first the next second, right?
 

KeithWalker

Joined Jul 10, 2017
3,063
Probably the reason for them printing that way is because the serial monitor recognizes embedded control characters and the display does not. What exactly is the format of the data from JSON? Does it output both values in a single message with a separator character or does it output two separate messages? Are the labels included in the messages?
Without that information I can not start to guess how to separate them.
 

Irving

Joined Jan 30, 2016
3,845
I answered this question in your other thread. Its considered rude to post multiple threads on the same subject and multiple times in the same thread (posts #1 and #5 in this thread).

The issues you have are:
a) you don't have a good understanding of control structures such as while() and the process of iterating through a list and acting on the variable content on each iteration, and
b) you should be using the JSON object library rather than parsing the string "by hand" to retrieve the content.

I suggest you do some reading on loops and iteration or look for a youtube tutorial on the same.
 
Top