1

I have an arduino nano, MCP3424 i2C ADC and a 128x64px i2C OLED display. The function is quite basic; the arduino receives information from the ADC and prints it to the screen as described in the code below.

#include <Fonts/FreeSerif9pt7b.h>

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

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

#define MCP 0x6E //7bit MCP3424 address
#define CH1 0x8C //PGA = 1, SPS = 3.75, One-Shot mode, channel 1, initiate new conversion.
#define CH2 0xAC //channel 2
#define CH3 0xCC //channel 3
#define CH4 0xEC //channel 4



void setup() {
  Serial.begin(9600);//Initiate Connection to computer
  Wire.begin();//Initiate Wire library
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    //Serial.println("SSD1306 allocation failed");
    for(;;);
  };
  delay(2000);
}

  int count = 0;
void loop() {

 RunProgram();
 count++;
 Serial.println(count);

}

int RunProgram(){
  int pins[] = {CH1, CH2, CH3, CH4};
  long results[] = {0, 0, 0, 0};
  //int count = 0;
  for (int i = 0; i < 4 ; i++) {
    Serial.println(F("Reading from MCP..."));
    results[i] = ReadMCP(pins[i]);
    Serial.print(F("Read from MCP channel: "));
    Serial.println(i);
    //delay(500);
  }
 Serial.println(F("Printing results..."));
 PrintResults(results[0], results[1], results[2], results[3]);
 //count++;
 //Serial.print(count);
 Serial.print(F(" Results printed: "));
}


int PrintResults(long res1, long res2, long res3, long res4) {

  //PrintResults(); takes 4 long ints, divides the oled display into 4 segments and prints the results on screen

  display.clearDisplay();
  Serial.println(F("Display cleared"));
  display.setTextSize(1);             
  display.setTextColor(WHITE);        
  display.setCursor(2, 3);             
  display.print(F("Ambient"));
  display.setCursor(66, 3);
  display.print(F("Probe 1"));
  display.setCursor(66, 35);
  display.print(F("Probe 3"));
  display.setCursor(2, 35);
  display.print(F("Probe 2"));
  Serial.println(F("text printed"));
  display.setCursor(3, 15);
  display.print(res1);
  display.setCursor(3, 47);
  display.print(res3);
  display.setCursor(66, 15);
  display.print(res2);
  display.setCursor(66, 47);
  display.print(res4);
  Serial.println(F("results printed"));
  /*display.setTextSize(2);
  display.setCursor(3, 15);
  if (x >= 1000) {
    display.println(x, 0);
  } else if (x >= 100) {
    display.println(x, 1);
  } else {
    display.println(x, 2);
  }*/
  display.drawRect(0, 0, 128, 64, WHITE);
  display.drawLine(0, 32, 128, 32, WHITE);
  display.drawLine(64, 0, 64, 64, WHITE);
  Serial.println(F("Borders printed"));
  display.display();
  Serial.println(F("Display updated"));
  delay(50);
  return 0;
  Serial.println(F("Return printed"));
}

long ReadMCP(int channel){
  //conversion takes the channel from which the reading is to be taken from and returns a number between 0 and 131071
  int x, y, z;
  long result = 0;

  Wire.beginTransmission(MCP);//begin transmission with ADC in Write mode
  Wire.write(channel);//Write the settings and channel for the ADC to the wire buffer
  Wire.endTransmission();//Send information in the buffer to the ADC
  delay(300);//wait for the ADC to take reading ( only 3.75 samples per second, roughly takes 266 milliseconds per reading)
  Wire.requestFrom(MCP, 3);//request 3 Bytes of information from MCP3424
  x = Wire.read();//read bytes
  y = Wire.read();
  z = Wire.read();

  //conversion of the three binary bytes to decimal
  if (x>1) {
    if (x%2){
      result += (1 * 65536L);//x * 65536 = x * 2^16
      result += (y * 256L);//y * 256 = y * 2^8
      result += z;
      result = -131072 + result;
    }else{
      result += (y * 256L);//y * 256 = y * 2^8
      result += z;
      result = -131072 + result;
    }

  } else {
    result += (x * 65536L);//x * 65536 = x * 2^16
    result += (y * 256L);//y * 256 = y * 2^8
    result += z;
  }
  return result;
}

The issue is, after a period of time (which so far has varied between 622 to 6 full loops of the program) the arduino freezes. I have found online that other people have experienced a similar problem. For example this page and this page this page seem to have others who are having the same issue. The fix offered on these pages, and others like it, were issues with memory. So I looked around for ways to reduce memory usage and came across this page. So I followed the advice and put all my strings in the F() function (or whatever it is, I'm not sure what it is or does) and segmented all my code into functions outside of the main loop. So I removed the majority of functions and variables from the main loop() function(before, all the functions in RunProgram() were in the main loop). However I am still encountering freezing issues. Can someone suggest reasons my arduino would freeze and ways to fix it?

9
  • 1
    Chances are it's the I2C communication that's locking up. I2C is not intended to be used over wires, and the internal pullup resistors in the MCU that are often used are far too high a value for proper I2C communication. Add 1kΩ resistors between each of SCL and SDA and the 5V pin of your Arduino.
    – Majenko
    Nov 27, 2019 at 14:41
  • Thanks for the suggestion @Majenko. For clarification all three parts of the circuit are soldered on to perforated board and the longest wire run is a few centimeters at most. I tried your suggestion, I had 10k pullups added to my circuit and changed them to and tested 4.6k, 2k, 560 and 220 ohm pullups all which had no effect on the locking up. I then also tried with the 2k ohm resistors changing the Wire clock speed to 50,000, half the speed. Still same issue.
    – Asyu7
    Nov 28, 2019 at 1:32
  • When the code is blocking, is at least one of the I2C lines (most probably the clock line) at low level? That would proof, that it is an I2C problem (since a released I2C bus has both lines at high level). If so, it is a difficult to debug problem. You can try to use another Arduino and try to mock one of the devices with it (so it sends the same data format, behaves about the same). Then check, if the problem goes away, if not try with the other device, then maybe with both devices replaced by Arduinos. Otherwise you would need an oszilloscope to analyse the data transmission.
    – chrisl
    Nov 28, 2019 at 8:07
  • @chrisl I removed the screen from the circuit and wired it in with just an arduino on a breadboard. after the arduino and screen froze while cycling through a very simple display program I measured both the SCA and SCL lines which were both high while frozen. I don't have an oscilloscope, though I have ordered another OLED to see If I just got a bad screen.
    – Asyu7
    Dec 2, 2019 at 0:53
  • @chrisl the screen by itself on the breadboard however is far more stable than on the circuit I made is there a way to find a difference between my circuit and the circuit on the breadboard
    – Asyu7
    Dec 2, 2019 at 2:52

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.