Serial monitor VS oled screen

Hi all.
I have a simple program that decodes morse code signals using a photodiode (I won't go into the electronics) and prints it to the serial monitor . It works perfectly fine so I tired adding a 0.96" i2c OLED screen for the decoded morse code to print to instead of printing the serial monitor. My issue now is that yes the dots and dashes print to the oled screen correctly , but the translations are weird. Weird being sometimes it does not translate and sometimes it translates the morse code to the wrong letter. I am so confused about why the program became dysfunctional after I introduced the OLED screen.

Does anyone know if the issue is with the OLED screen itself or my program?

the code using the serial monitor:


const int sensorPin = A0; //  analog pin for the photodiode
unsigned long pulseStartTime = 0;
unsigned long pulseEndTime = 0;
unsigned long pulseDuration = 0;
unsigned long lastPulseTime = 0;
bool isNewWord = false;
bool isNewAlphabet = false;
unsigned long alphabetStartTime = 0;

String receivedCode = "";

void setup() {
  Serial.begin(9600);
  pinMode(sensorPin, INPUT);
}

void loop() {
  int sensorValue = analogRead(sensorPin);
  
  // Check if the voltage level is above 2V
  if (sensorValue > 409) { // Assuming a 5V reference (adjust) WAS409
    while (digitalRead(sensorPin) == LOW) {}

    pulseStartTime = millis();

    while (digitalRead(sensorPin) == HIGH) {}

    pulseEndTime = millis();
    pulseDuration = pulseEndTime - pulseStartTime;

    if (isNewWord && (millis() - lastPulseTime > 5000)) 
    {
      Serial.print(" / ");
      isNewWord = false;
      convertMorseToAlphabet(receivedCode);
      receivedCode = "";  // Reset the received Morse code
    }

    if (!isNewAlphabet && (millis() - lastPulseTime > 2000) && (millis() - lastPulseTime < 3000)) 
    {
      Serial.print("$");
      isNewAlphabet = true; // Set the flag to indicate the end of an alphabet
    } 
    else
    {
      isNewAlphabet = false;
    }
    
    if (pulseDuration > 100 && pulseDuration < 400)
    {
      Serial.print(".");
      isNewWord = true;
      receivedCode += ".";
    } 
    else if (pulseDuration > 800) 
    {
      Serial.print("-");
      isNewWord = true;
      receivedCode += "-";
    }

    lastPulseTime = millis();

    delay(50);
  }
}

// Function definition for convertMorseToAlphabet
void convertMorseToAlphabet(String morseCode) {
  static String morseLetters[] = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-",
                             ".-.", "...", "-", "..-", "...-", ".--.", "-..-", "-.--", "--..", "#"};
  int i = 0;
  
  while (morseLetters[i] != "#") 
  {
    if (morseLetters[i] == morseCode) 
    {
      Serial.print(char('A' + i));
      break;
    }
    i++;
  }
  
  if (morseLetters[i] == "#") 
  {
    Serial.println(""); // if input code doesn't match any letter, error
  }
}

the code using the oled screen :


#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>


#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

const int sensorPin = A0; //  analog pin for the photodiode
unsigned long pulseStartTime = 0;
unsigned long pulseEndTime = 0;
unsigned long pulseDuration = 0;
unsigned long lastPulseTime = 0;
bool isNewWord = false;
bool isNewAlphabet = false;
unsigned long alphabetStartTime = 0;

String receivedCode = "";

void setup() {
  Serial.begin(9600);
  pinMode(sensorPin, INPUT);

  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { 
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }
  delay(2000);
      display.clearDisplay();
      display.setTextSize(1);
      display.setTextColor(SSD1306_WHITE);
      display.setCursor(0, 0);
      display.println("WELCOME TO THE MORSE CODE RECEIVER!");
      
}



void loop() {
  int sensorValue = analogRead(sensorPin);
  
  // Check if the voltage level is above 2V-409
  if (sensorValue > 409) { // 5V reference 
    while (digitalRead(sensorPin) == LOW) {}

    pulseStartTime = millis();

    while (digitalRead(sensorPin) == HIGH) {}

    pulseEndTime = millis();
    pulseDuration = pulseEndTime - pulseStartTime;

    if (isNewWord && (millis() - lastPulseTime > 5000)) 
    {
    display.print(" / ");
      isNewWord = false;
      convertMorseToAlphabet(receivedCode);
      receivedCode = "";  //reset received Morse code
    }

    if (!isNewAlphabet && (millis() - lastPulseTime > 2000) && (millis() - lastPulseTime < 3000)) 
    {
      display.print("$");
      isNewAlphabet = true; //set flag to indicate the end of alphabet
    } 
    else
    {
      isNewAlphabet = false;
    }
    
    if (pulseDuration > 100 && pulseDuration < 400)
    {
      display.print(".");
      isNewWord = true;
      receivedCode += ".";
    } 
    else if (pulseDuration > 800) 
    {
      display.print("-");
      //  display.display();
      isNewWord = true;
      receivedCode += "-";
    }

    lastPulseTime = millis();

    delay(50);
  }
  display.display();
}

// Function definition for convertMorseToAlphabet
void convertMorseToAlphabet(String morseCode) {
  static String morseLetters[] = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-",
                             ".-.", "...", "-", "..-", "...-", ".--.", "-..-", "-.--", "--..", "#"};
  int i = 0;
  
  while (morseLetters[i] != "#") 
  {
    if (morseLetters[i] == morseCode) 
    {
      display.print(char('A' + i));
     display.display();
      break;
    }
    i++;
  }
  
  if (morseLetters[i] == "#") 
  {
    display.println("ERROR"); // if input code doesn't match any letter, error
     display.display();
  }
  
}

just an idea worth exploring:

displays can be slow and you call display.display(); at every loop ➜ may be you slowed down the code too much and you are messing with the calculation for the pulseDuration or missing pulses altogether

1 Like

I thought so too and then I just added one display.display() command at the end of the whole loop and ended up with the same issue .
Do you think that even one display.display() is enough to slow it down enough to mess up the whole thing?
Regards

you could time it

uint32_t t0 = micros(); // <=== note the time before calling display
display.display();
uint32_t t1 = micros(); // <=== note the time after calling display
Serial.print("∆t display : "); 
Serial.print(t1 - t0);  // <=== print the duration of the call (assuming it's blocking)
Serial.println("µs);

but really you should call display only when something has changed

1 Like

Cool I'll give this a go.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.