Porting WiFi app that displays weather from GIGA and Teensy boards to Uno R4 Wifi

This started off as just an experiment!

Not sure how many might be interested, But after we (@Merlin513 and I) was able to
use the WiFi on some different Teensy boards (using some Esp32 boards or Teensy WIrelessShield by sparkfun) for WiFi and making a version that works on the Arduino Giga,
I wondered how hard it would be to make it work on Arduino Uno R4 WiFI.

More details about these other setups in the forum threads:

Playing with Zephyr V1.0.0 on GIGA and Wifi - Mega / GIGA R1 WiFi - Arduino Forum

Teensy 4.x + ESP32 Stack | Page 4 | Teensy Forum

It works!

Short Answer: It could be done

The sketch appears to be working reasonably well


If you touch the screen on one of the days, it brings up more details for the day

If you click on the keyboard near the upper right it brings up keyboard screen

Note the images above display I was using has a capacitive touch setup.
Amazon.com: Hosyond 3.5 inch 320x480 IPS Capacitive Touch Screen LCD Module SPI Serial ST7796U Driver for Arduino R3/Mega2560 : Electronics

It also works with ones with Resistive Touch


Amazon.com: Hosyond 4.0 Inches 480x320 TFT Touch Screen LCD Display Module SPI ST7796S Driver for Arduino R3/Mega2560 : Electronics

I pushed up the sketches, to my github project, which has some of the different sketches and tests, that I have done with the Uno R4...

UNOR4-stuff/test_sketches at main · KurtE/UNOR4-stuff

Libraries Used

WiFi It uses WiFiS3 - is installed with Arduino board

Display: Currently using my own ST7796 library that was adapted from some others including ST77XX_t3.... I pushed a copy of it up to:

Touch: Depending on Capacitive or Resistive.
Capacitive: Adafruit_FT6206 (library manager)
Resistive: XPT2046_Touchscreen (library manager)

Json ArduinoJson (library manager)

Challenges along the way

It was a challenge as the Uno R4 WiFi only has 256k Flash and 32K Ram. Where for example the T4.1 has like 8MB flash and 1024K memory... Giga 2MB Flash 1GB Ram...

I did a quick test to see if the WiFi would retrieve the weather information, from

The Test sketch worked.

Now to try to display it on a TFT display. I decided to go with an ST7796 display as I have been using these display, except for the GIGA where I am using the GIGA Shield.

Library? I could use Adafruit_st77xx library, but it uses differents fonts and the like, so I ported our ST77xx_t3 library to run on the Renesas setup, I already have versions that run on MBED an Zephyr.

Getting it to fit onto the Flash. The sketch we have setup has something like 20+ images
which were converted to simple bitmap RGB565 header files, each with 64 * 64 * 2 bytes of data. which consumed something like 180KB of the flash. Adding in all of the codes plus font files exceeded the flash. The first attempt was to instead of converting the PNG files to the bitmap format, we simply dump the bytes of the PNG file into header files and use PNGDEC to convert them on the fly. However PNGDEC requires about 45K of free ram to run, which is hard on a board with only 32K of Ram... The current solution was I ran these images again through a sketch which converted any of the images that used <= 256 colors into a palette image which cuts the image in about half... This was sufficient until I enabled more code for touch and a screen based keyboard entry, solved by removing the lines at the start and end of the image which were all BLACK... The sketch that I used to do the compress of the images is: compress_airy_images which I ran on a Teensy 4.1, as I am more used to it, and the like, including it has Serial.printf ;)

Things I may Change

  1. I hate using arduino_secrets.h - May store, SSID, Password, and current Location in EEPROM, if it is not present may prompt for it...

  2. May get some Display shield that plugs into R4, so can have setup without jumper wires.

But: Probably won't be doing very much more with this as it was more a challenge to myself. So will probably return to my previous distraction.

@KurtE

Gave it a try with my ST7796 sketch with XPT touch. Worked like a charm. Nice job on getting everything to fit. The compression method may come in handy later have to go dig into that one - will put it on the TODO list :slight_smile:

I just pushed up a version, that saves the SSID/Password to the EEPROM. If the data is not correct (simple checksum), it will prompt you for these values and then update it to the EEPROM.

It also saves away the last location you searched for weather on,
and it uses that at start up time.

With the saving SSID/Password in EEPROM. If there is a problem with the saved information,
you can force it to prompt you for it, by jumpering the D2 pin to ground.

I also fixed a bug or two along the way.

Well, I could not leave this undone... :laughing:

So, I purchased one of these from Amazon.com:

It is an HX8357D display like the STM7796 I am using with jumper wires. It is setup as an 8 parallel connection whereas the other displays I have been using are SPI.

The display arrived here yesterday.

I am using the library: DIYables_TFT_Touch_Shield, which uses the Adafruit_GFX class as the base class.

So far I have not changed anything in their library, which also has touch support built in.
So I created a version that runs on this, with mostly parts from the other UNOR4 sketch I
posted above, plus parts from our port to the GIGA...

Not perfect, but probably good enough for play:

Main display:

Clicking on one of the days:

And clicking on the keyboard icon to get to keyboard:

Note: this display uses just about every UNO IO pin, so currently I have
the code that shorting pin 2 to ground would reset the stuff stored to EEPROM.
Will probably reimplement using different pin, probably either D0 or D1 as I don't
think the shield uses these pins.

As I mentioned above, I have changed their library at all, they try to make it about as fast
as they can by writing the data directly to port registers: For the Uno R4 WiFi:

#elif defined(ARDUINO_UNOR4_WIFI)
#define RD_PORT    R_PORT0
#define RD_PIN     14
#define WR_PORT    R_PORT0
#define WR_PIN     0
#define CD_PORT    R_PORT0
#define CD_PIN     1
#define CS_PORT    R_PORT0
#define CS_PIN     2
#define RESET_PORT R_PORT1
#define RESET_PIN  1

#define DATA_PORT3 R_PORT3
#define DATA_PORT1 R_PORT1
#define DATA_MASK3 0x18
#define DATA_MASK1 ((1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<11)|(1<<12))

#define WRITE_8(val) do { \
    DATA_PORT3->PODR = (DATA_PORT3->PODR & ~DATA_MASK3) \
        | (((val & 0x01) ? (1<<4) : 0) | ((val & 0x02) ? (1<<3) : 0)); \
    DATA_PORT1->PODR = (DATA_PORT1->PODR & ~DATA_MASK1) \
        | (((val & 0x04) ? (1<<4) : 0) | ((val & 0x08) ? (1<<5) : 0) \
        | ((val & 0x10) ? (1<<6) : 0) | ((val & 0x20) ? (1<<7) : 0) \
        | ((val & 0x40) ? (1<<11) : 0) | ((val & 0x80) ? (1<<12) : 0)); \
} while (0)
#define SET_DATA_DIR_OUT() do { \
    DATA_PORT3->PDR |= DATA_MASK3; \
    DATA_PORT1->PDR |= DATA_MASK1; \
} while (0)
#define SET_CONTROL_DIR_OUT() do { \
    RD_PORT->PDR |= (1 << RD_PIN); \
    WR_PORT->PDR |= (1 << WR_PIN); \
    CD_PORT->PDR |= (1 << CD_PIN); \
    CS_PORT->PDR |= (1 << CS_PIN); \
    RESET_PORT->PDR |= (1 << RESET_PIN); \
} while (0)
#define PIN_LOW(port, pin)   ((port)->PODR &= ~(1 << (pin)))
#define PIN_HIGH(port, pin)  ((port)->PODR |=  (1 << (pin)))
#define PIN_OUTPUT(port, pin) ((port)->PDR |= (1 << (pin)))

In most cases I try to avoid using the PODR, as suppose in the line:

    DATA_PORT3->PODR = (DATA_PORT3->PODR & ~DATA_MASK3) \
        | (((val & 0x01) ? (1<<4) : 0) | ((val & 0x02) ? (1<<3) : 0)); \

That after your retrieved the current value of the PODR register, an interrupt
happens, where potentially during the ISR one or more of the other pins of PORT3 changes
state, and then after the return from the ISR, the code that masks and sets the values of the pins of the display and the stores out the new value will toss the updated pin changes
that happened during the ISR. (I have spent more time than I wish to remember tracking down strange errors where something like that happened).

Wondering if it would be any slower to simply do something like:

DATA_PORT3->BSRR = DATA_MASK3 << 16;
DATA_PORT3->BSRR =  (((val & 0x01) ? (1<<4) : 0) | ((val & 0x02) ? (1<<3) : 0));

The first clears all of the bits that we might set, and then the second sets those that are HIGH...

But as doing this for the fun of it... Not sure if I will change them or not.

Current sketch is up at:

Kurt

Really cool project I may try it myself but uh don't those lcd pannels need logic level converters when being use with 5v boards like arduino uno R4 wifi from the pictures in those listings those displays don't have them built in.

Those shield displays have the level converters built in for the display interface. Not for the SD card. Those two SMD ICs you can see on the image of the back are the ICs in question.

On the capacitive touch panel yes but on the red resistive touch one the only ic besides the ldo on the back is the XTP2046 12 bit adc for the touchstone.

Apples and oranges.

The shields are resistive touch and include level converters for the display.

Displays using XPT2046 will be SPI and will not be shields.

And as I said "Those shield displays have the level converters built in".

These displays have a resistive touch, using analogReads. 4 of the pins are used on both the display part and the touch part, which they change modes (digitalWrites... analogRead)

Note: I also tried these displays on the GIGA fully works on MBED, and display works on
Zephyr and @Merlin513 and I have made some changes that touch is starting to work.
Ditto for UNOQ

Congratulations on having your project featured in the Arduino Blog!