Get data via UART and print on OLED with SPI

Hello everybody,

I’m currently working on a project, where I control a BLDC motor with a potentiometer and some more things and in the end I want to print those values to an adafruit SSD_1306 OLED display. Therefore I need to get some data from the so called VESC (an ESC spezialised for e-skateboards etc). The VESC sends data via UART to my Arduino UNO Rev3. This alone works and I can see the data coming in in the serial monitor.
Also the display works fine an shows some strings and variables.
But I have major issues when getting data via the uart and print those values on the OLED. As soon as I uncomment the “Uart.getVescValue” which initializes the process of receiving the data and upload it to the UNO the OLED won’t turn on, my potentiometer does not work anymore and my BLDC motor obviously does not start anymore.
I tried all this with the I2C as well and with different baud rates, same issue.

To wrap things up, I get UART data (using SolidGeeks Library GitHub - SolidGeek/VescUart: An Arduino library for interfacing with the VESC over UART), I can write to my OLED as long as I do not receive data from the UART. Receiving data results in OLED turns off and poti does not work anymore.

In the picture you can see the output of my OLED. The “poti” value is no data from the UART, this value comes straight from the A0 Pin.

Is it just not possible with the Arduino UNO to read from the UART and send over SPI to the OLED due to only one Serial Port?
Or do I need to include another virtual serial port with the help of the <softwareSerial.h> library? Which I actually tried already but I guess I don’t really know how to do this.

Any help is highly appreciated. Thanks

Cheers
Heiko

Here the code:

#include <VescUart.h>
#include <Servo.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>


#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// *** SPI ***Declaration for SSD1306 display connected using software SPI (default case):
  #define OLED_MOSI   9
  #define OLED_CLK   10
  #define OLED_DC    11
  #define OLED_CS    12
  #define OLED_RESET -1
  Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,
  OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

/* Used for I²C
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
*/
VescUart UART;
Servo BLDC;

const uint8_t VescOutputPin = 6;

void setup() {
  Serial.begin(9600);
  
    // ***___ setup für UART___***
  while (!Serial) {
    ;
  }
  UART.setSerialPort(&Serial);
  //_______________________________________***


  
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { 
  Serial.println("SSD1306 allocation failed");
  for(;;); // Don't proceed, loop forever
}


  // ***___ setup für PWM___***
  BLDC.attach(VescOutputPin);
  BLDC.writeMicroseconds(1480);
  //***_________________________________***


  // ***___ setup für OLED___***
  display.begin(SSD1306_SWITCHCAPVCC);
  display.display();
  delay(1000);
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(5, 4);
  display.println("Projektarbeit");
  display.setCursor(30, 24);
  display.println("Heiko");
  display.setCursor(55, 44);
  display.println("2020");
  display.display();
  delay(4000);
  //***_________________________________***

}


void loop() {
  int PotiPin = analogRead(A0);

  BLDC.writeMicroseconds(map(analogRead(PotiPin), 0 , 1023, 1000, 2419)); //PWM with Poti Pin

  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(5, 44);
  display.println("Poti:");
  display.setCursor(80, 44);
  display.print(PotiPin);
  display.setCursor(5, 4);
  display.println("Volt:");
  display.setCursor(5, 24);
  display.println("RPM:");
  display.display();  



  //***_____Get values via UART from VESC_____***

/*  if (UART.getVescValues()) {


    Serial.println("RPM");
    Serial.println(UART.data.rpm);

    Serial.println("Tachometer");
    Serial.println(UART.data.tachometer);

    Serial.println("Input Voltage");
    Serial.println(UART.data.inpVoltage);

    Serial.println("Average Motor current");
    Serial.println(UART.data.avgMotorCurrent);

    Serial.println("Average Input Current");
    Serial.println(UART.data.avgInputCurrent);
  }
 
*/ 
  //Input Voltage
  display.setCursor(80, 4);
  display.println(UART.data.inpVoltage);

 
  //RPM Werte
  display.setCursor(80, 24);
  display.print(UART.data.rpm);
  display.display();
   
  }

The SSD1306 allocates 1kB of RAM at runtime, so you have to save as much RAM as possible in your sketch otherwise you run out of it.
You waste much RAM by not using the F() macro for printing constant strings.

As you failed to provide a link to your VescUART library I cannot check the memory usage of that one.

Thanks for the first hint @pylon , I will insert the F() macro asap to save up some RAM.

I'm using the SolidGeek Library. Here is the link to the VescUART Library:

VescUart Library SolidGeek

I would check the memory usage of the library myself but to be honest. I don't know where to look for this.

Update:
After implementing the F() macro:
"Sketch uses 16572 bytes (51%) of program storage space. Maximum is 32256 bytes.
Global variables use 586 bytes (28%) of dynamic memory, leaving 1462 bytes for local variables. Maximum is 2048 bytes."

I reckon this should be enough left over RAM for the SSD1306

I reckon this should be enough left over RAM for the SSD1306

No, because your VescUART library uses over 512 bytes of RAM at runtime for message buffers so the complete sketch uses more than 2kB while running. I don't know what kind of messages the VescUART library is handling but you might decrease the buffer sizes and introduce content length checking instead (depends on the actual size of the messages sent). If you can decrease the buffer size to 128 you might get away with the available RAM.

Thanks for helping me out.

You were right, that the buffer uses to much buffer. I couldn't get the buffer size reduced but I tried the exact same code on a Mega and it works just fine.

Thanks again.

Cheers
Heiko