My teensy freezes running this code 90% of the time now... Any ideas?

Status
Not open for further replies.

NeTgHoSt

Member
Good evening from California. I have a serious intermittent issue with my Teensy 3.2 regularly freezing in the middle of my code, whereafter it will not reboot, even with a power cycle. Sometimes it will turn back on, but I haven't figured out what is preventing it from rebooting successfully. I posted another thread a little while back, my first post, about it not loading a bitmap image properly. It would load sections of repeating colors the same size as the intended bitmap. It was never resolved, mostly because of this new issue... Here is the photo of that project:

20200524_215138.jpg

Soon after posting that, my teensy 3.2 began doing this freezing thing. I removed it from that breadboard, and started a fresh project to make sure connections weren't the issue. I removed the thermistor, MicroSD card reader, (only needed to display that color bitmap) added an HC-SR04 Ultrasonic Sensor, and changed out the passive buzzer for an active one; controlled and powered indirectly using a transistor. Also added 2 buttons to switch between functions; my code has evolved quite a bit as my knowledge improved over the last couple weeks. The previous setup used no buttons, as you can see. I also replaced the delay()'s with millis() as suggested in the other thread. Here is the current breadboard setup: (BTW, this setup worked fine for many days of intermittent testing without fail)

BackupAlarm.jpg

I was able to get it to turn on again just now to take 2 photos of the 2 functions running. As I typed all this, the screen blanked out yet again during the idleDisplay function. At the moment, the function is programmed to display the battery level reading (0-1024 on the left, map from 0-100 on the right) from A9 on the OLED in plain text (for debugging):

IdleDisplay.jpg

Here is the other distanceDisplay function, which suprisingly runs fine without fail; even though it would always fail on the last project setup. It only seems to freeze after running the idleDisplay function for some time.

DistanceDisplay.jpg

I was super proud of myself for getting this far.. and now I'm feeling quite down, thinking I must've overlooked something important that may be causing these issues that I'm unable to pin down. It seemed to be working fine until I added the battery level reading.. unless that is coincidence. Help would be very much appreciated! Let me know what other information might be needed about my setup. Thank you!!!

Current Code:
Code:
////////////////////////////////////////////////////////////////////////////////////
/////Ultrasonic Distance Meter aka Backup Proximity Alert for vehicular usage///////
////////////////////////////////////////////////////////////////////////////////////

//Libraries
#include <NewPing.h>
#include <Adafruit_GFX.h>
#include <ST7735_t3.h>
#include <SPI.h>
#include "Buzzer.h"

//Compiler / Global Defines
#define TFT_MOSI  11      //Signal input pin      (SDA)
#define TFT_SCLK   13     //Clock pin             (SCK)
#define TFT_DC   20       //Data/command pin      (DC )
#define TFT_CS   15       //Chip select pin       (CS )
#define TFT_RST  14       //Reset pin             (RST)
#define TFT_BLK  12       //Backlight Control pin (BLK)
#define TRIGGER_PIN  16   // Teensy pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     19   // Teensy pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 200  // Max ping distance (in cm). Max distance is 400-500cm.
#define BUZZER_PIN_SIG 6  //Beeper pin
#define battLevelPin A9

//Sensor and Display Connection Setup etc.
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.
ST7735_t3 tft = ST7735_t3(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);
Buzzer buzzer(BUZZER_PIN_SIG);

boolean modeState;
boolean ranDistanceSetup = false;
boolean ranIdleSetup = false;

const unsigned char PROGMEM flag [] = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0x00, 0x00, 0x00,
  0x0C, 0x3C, 0x3F, 0x00, 0x00, 0x00, 0x0C, 0x3C, 0x3F, 0x00, 0x00, 0x00, 0x0C, 0x3C, 0x3F, 0x00,
  0x00, 0x00, 0x0C, 0x3C, 0x3F, 0x00, 0x00, 0x00, 0x0F, 0xC3, 0xC3, 0xFF, 0xFF, 0xF8, 0x0F, 0xC3,
  0xC3, 0xFF, 0xFF, 0xFC, 0x0F, 0xC3, 0xC3, 0xF0, 0xF0, 0xFC, 0x0F, 0xC3, 0xC3, 0xF0, 0xF0, 0xFC,
  0x0C, 0x3C, 0x3F, 0xF0, 0xF0, 0xFC, 0x0C, 0x3C, 0x3F, 0xF0, 0xF0, 0xFC, 0x0C, 0x3C, 0x3F, 0x0F,
  0x0F, 0x0C, 0x0C, 0x3C, 0x3F, 0x0F, 0x0F, 0x0C, 0x0F, 0xC3, 0xC3, 0x0F, 0x0F, 0x0C, 0x0F, 0xC3,
  0xC3, 0x0F, 0x0F, 0x0C, 0x0F, 0xC3, 0xC3, 0xF0, 0xF0, 0xFC, 0x0F, 0xC3, 0xC3, 0xF0, 0xF0, 0xFC,
  0x0C, 0x3C, 0x3F, 0xF0, 0xF0, 0xFC, 0x0C, 0x3C, 0x3F, 0xF0, 0xF0, 0xFC, 0x0C, 0x3C, 0x3F, 0x0F,
  0x0F, 0x0C, 0x0C, 0x3C, 0x3F, 0x0F, 0x0F, 0x0C, 0x0F, 0xFF, 0xFF, 0x0F, 0x0F, 0x0C, 0x0F, 0xFF,
  0xFF, 0x0F, 0x0F, 0x0C, 0x0C, 0x03, 0x1E, 0xF0, 0xF0, 0xFC, 0x0C, 0x03, 0x3C, 0xF0, 0xF0, 0xFC,
  0x0C, 0x03, 0x70, 0xF0, 0xF0, 0xFC, 0x0C, 0x03, 0xE0, 0xF0, 0xF0, 0xFC, 0x0C, 0x03, 0xFF, 0xFF,
  0xFF, 0xFC, 0x0C, 0x03, 0xFF, 0xFF, 0xFF, 0xFC, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

void setup() {
  pinMode(TFT_BLK, OUTPUT);
  digitalWrite(TFT_BLK, HIGH);
  pinMode(5, INPUT_PULLUP);
  pinMode(7, INPUT_PULLUP);
  tft.initR(INITR_MINI160x80_ST7735S);
  tft.setRotation(3);
  tft.fillScreen(ST7735_BLACK);
  Serial.begin(9600);
  Serial.print("TFT Init!");
}

int mode = 0;

void loop() {
  if (mode == 0) {
    idleDisplay();
  } else {
    distanceDisplay();
  }

  if (digitalRead(5) == LOW) {
    mode = 0;
    Serial.println("mode 0");
  }
  if (digitalRead(7) == LOW) {
    mode = 1;
    Serial.println("mode 1");
  }
}

void distanceDisplaySetup() {
  tft.fillScreen(ST7735_GREEN);                 
  tft.fillRect(2, 2, 156, 76, ST7735_BLACK);    
  tft.setTextColor(ST7735_YELLOW, ST7735_BLACK);
  tft.setCursor(52, 4);
  tft.setTextSize(2);
  tft.print("Feet:");
  tft.setTextSize(5);
  tft.drawLine(27, 20, 132, 20, ST7735_GREEN);
  tft.drawLine(26, 2, 26, 77, ST7735_GREEN);
  tft.drawLine(133, 2, 133, 77, ST7735_GREEN);
  tft.setTextColor(ST7735_RED, ST7735_BLACK);
  ranDistanceSetup = true;
  ranIdleSetup = false;
}

int inchmap = 0;
int inchmapchangevalue = 0;

void distanceDisplay() {
  if (ranDistanceSetup == false) {
    distanceDisplaySetup();
  }

  float inchAverage = 0;
  for (int i = 1; i < 10; i++) {
    inchAverage += sonar.ping_in();
  }
  float inch = (inchAverage / 10) * 100;
  float feet = (inch / 12) / 100;
  inchmap = map(inch, 0, 12000, 1, 75);
  inchmap = constrain(inchmap, 1, 75);
  if (inchmapchangevalue != inchmap) {
    tft.fillRect(2, 2, 23, 75, ST7735_RED);
    tft.fillRect(134, 2, 23, 75, ST7735_RED);
    tft.fillRect(2, 2, 23, inchmap, ST7735_BLACK);
    tft.fillRect(134, 2, 23, inchmap, ST7735_BLACK);
    tft.drawFloat(feet, 1, 36, 32);
    inchmapchangevalue = inchmap;
  }

  if (inch <= 1200 && inch > 1) {
    fastBeep();
  }

  if (inch <= 3600 && inch > 1200) {
    medBeep();
  }

  if (inch <= 7200 && inch > 3600) {
    slowBeep();
  }

  else {
    for (int x = 0; x < 50; x++) {
      delay(1);
    }
  }
}

unsigned int x = 57;
unsigned int y = 16;

void idleDisplaySetup() {
  buzzer.off();
  tft.fillScreen(ST7735_BLACK);
  tft.drawBitmap(x, y, flag, 48, 48, ST7735_RED);
  tft.setTextSize(1);
  tft.setTextColor(ST7735_YELLOW, ST7735_BLACK);
  ranIdleSetup = true;
  ranDistanceSetup = false;
}

unsigned int battLevel = 0;
unsigned int battLevelChange = 0;

void idleDisplay() {
  if (ranIdleSetup == false) {
    idleDisplaySetup();
  }
  unsigned int battAdcAverage = 0;
  for (int i = 1; i < 10; i++) {
    battAdcAverage += analogRead(battLevelPin);
  }
  unsigned int battAdcReading = (battAdcAverage / 10);
  unsigned int battLevel = map(battAdcReading, 640, 740, 0, 100);
  battLevel = constrain(battLevel, 0, 100); 
  if (battLevelChange != battLevel) {
    tft.setCursor(10, 40);
    tft.print("     ");
    tft.setCursor(120, 40);
    tft.print("     ");
    tft.drawNumber(battAdcReading, 10, 40);
    tft.drawNumber(battLevel, 120, 40);
    for (int x = 0; x < 100; x++) {
      delay(1);
    }
  }
  battLevelChange = battLevel;

}

unsigned long slowinterval = 300;
unsigned long medinterval = 150;
unsigned long fastinterval = 75;
unsigned long previousMillis = 0;

bool buzzerState = false;

void slowBeep() {
  unsigned long currentMillis = millis();
  if ((unsigned long)(currentMillis - previousMillis) >= slowinterval) {
    previousMillis = currentMillis;
    if (buzzerState == false) {
      buzzerState = true;
    }
    else {
      buzzerState = false;
    }
    if (buzzerState == true) {
      buzzer.on();
    }
    if (buzzerState == false) {
      buzzer.off();
    }
  }
}
void medBeep() {
  unsigned long currentMillis = millis();
  if ((unsigned long)(currentMillis - previousMillis) >= medinterval) {
    previousMillis = currentMillis;
    if (buzzerState == false) {
      buzzerState = true;
    }
    else {
      buzzerState = false;
    }
    if (buzzerState == true) {
      buzzer.on();
    }
    if (buzzerState == false) {
      buzzer.off();
    }
  }
}

void fastBeep() {
  unsigned long currentMillis = millis();
  if ((unsigned long)(currentMillis - previousMillis) >= fastinterval) {
    previousMillis = currentMillis;
    if (buzzerState == false) {
      buzzerState = true;
    }
    else {
      buzzerState = false;
    }
    if (buzzerState == true) {
      buzzer.on();
    }
    if (buzzerState == false) {
      buzzer.off();
    }
  }
}

How my code works:

It powers up into "mode 0" at startup, the "idleDisplay" mode which calls "idleDisplaySetup" function once to display the red flag, and then returns to "idleDisplay" function to show the voltage readings from A9 to the left, with a % reading to the right. This code repeats (not using "delay()") until the button for "mode 1" is pressed. "Mode 1" runs the "distanceDisplay" function, which calls "distanceDisplaySetup" once, and then loops that code using the newPing library until the "mode 0" button is pressed again, taking it back into the "idleDisplay" function, etc. The buzzer is controlled by "if" statements in the "distanceDisplay" function, using 3 different "if" statements for 3 different beeping speeds, depending on distance. It works as expected, when it's not bricked.

There are some "Buzzer.h" files included in separate tabs to make the "buzzer.on()" functions work. I can include those if needed.
 
Still desperate for a solution.. Teensy 3.2 still freezing/blanking display.

Update:
Still haven't solved this. I found another instance of my using "delay()" instead of "millis()" and fixed it, but my display still blanked out after maybe 10 seconds on battery power. Input voltage is 4.2V to VIN pin. Should be enough. When plugged into USB cable with battery connection switched off, 5v power for devices is drawn from the VUSB pin through a diode. Could the problem be related to the OLED/HC-SR04 not getting the full 5v when battery powered? I measured current draw at 78Ma. My program runs just fine until it sits in the idleDisplay mode for a random amount of time, and then the screen blanks out and device wont restart. ANYONE have ANY idea what I can try next, please? Here is my updated code with last remaining delays switched out for millis:

Code:
////////////////////////////////////////////////////////////////////////////////////
/////Ultrasonic Distance Meter aka Backup Proximity Alert for vehicular usage///////
////////////////////////////////////////////////////////////////////////////////////

//Libraries
#include <NewPing.h>
#include <Adafruit_GFX.h>
#include <ST7735_t3.h>
#include <SPI.h>
#include "Buzzer.h"

//Compiler / Global Defines
#define TFT_MOSI  11      //Signal input pin      (SDA)
#define TFT_SCLK   13     //Clock pin             (SCK)
#define TFT_DC   20       //Data/command pin      (DC )
#define TFT_CS   15       //Chip select pin       (CS )
#define TFT_RST  14       //Reset pin             (RST)
#define TFT_BLK  12       //Backlight Control pin (BLK)
#define TRIGGER_PIN  16   // Teensy pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     19   // Teensy pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 200  // Max ping distance (in cm). Max distance is 400-500cm.
#define BUZZER_PIN_SIG 6  //Beeper pin
#define battLevelPin A9

//Sensor and Display Connection Setup etc.
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.
ST7735_t3 tft = ST7735_t3(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);
Buzzer buzzer(BUZZER_PIN_SIG);

boolean modeState;
boolean ranDistanceSetup = false;
boolean ranIdleSetup = false;
boolean showFirstBattLevel = false;

const unsigned char PROGMEM flag [] = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0x00, 0x00, 0x00,
  0x0C, 0x3C, 0x3F, 0x00, 0x00, 0x00, 0x0C, 0x3C, 0x3F, 0x00, 0x00, 0x00, 0x0C, 0x3C, 0x3F, 0x00,
  0x00, 0x00, 0x0C, 0x3C, 0x3F, 0x00, 0x00, 0x00, 0x0F, 0xC3, 0xC3, 0xFF, 0xFF, 0xF8, 0x0F, 0xC3,
  0xC3, 0xFF, 0xFF, 0xFC, 0x0F, 0xC3, 0xC3, 0xF0, 0xF0, 0xFC, 0x0F, 0xC3, 0xC3, 0xF0, 0xF0, 0xFC,
  0x0C, 0x3C, 0x3F, 0xF0, 0xF0, 0xFC, 0x0C, 0x3C, 0x3F, 0xF0, 0xF0, 0xFC, 0x0C, 0x3C, 0x3F, 0x0F,
  0x0F, 0x0C, 0x0C, 0x3C, 0x3F, 0x0F, 0x0F, 0x0C, 0x0F, 0xC3, 0xC3, 0x0F, 0x0F, 0x0C, 0x0F, 0xC3,
  0xC3, 0x0F, 0x0F, 0x0C, 0x0F, 0xC3, 0xC3, 0xF0, 0xF0, 0xFC, 0x0F, 0xC3, 0xC3, 0xF0, 0xF0, 0xFC,
  0x0C, 0x3C, 0x3F, 0xF0, 0xF0, 0xFC, 0x0C, 0x3C, 0x3F, 0xF0, 0xF0, 0xFC, 0x0C, 0x3C, 0x3F, 0x0F,
  0x0F, 0x0C, 0x0C, 0x3C, 0x3F, 0x0F, 0x0F, 0x0C, 0x0F, 0xFF, 0xFF, 0x0F, 0x0F, 0x0C, 0x0F, 0xFF,
  0xFF, 0x0F, 0x0F, 0x0C, 0x0C, 0x03, 0x1E, 0xF0, 0xF0, 0xFC, 0x0C, 0x03, 0x3C, 0xF0, 0xF0, 0xFC,
  0x0C, 0x03, 0x70, 0xF0, 0xF0, 0xFC, 0x0C, 0x03, 0xE0, 0xF0, 0xF0, 0xFC, 0x0C, 0x03, 0xFF, 0xFF,
  0xFF, 0xFC, 0x0C, 0x03, 0xFF, 0xFF, 0xFF, 0xFC, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

void setup() {
  pinMode(TFT_BLK, OUTPUT);
  digitalWrite(TFT_BLK, HIGH);
  pinMode(5, INPUT_PULLUP);
  pinMode(7, INPUT_PULLUP);
  tft.initR(INITR_MINI160x80_ST7735S);
  tft.setRotation(3);
  tft.fillScreen(ST7735_BLACK);
  Serial.begin(9600);
  Serial.print("TFT Init!");
}

int mode = 0;

void loop() {
  if (mode == 0) {
    idleDisplay();
  } else {
    distanceDisplay();
  }

  if (digitalRead(5) == LOW) {
    mode = 0;
    Serial.println("mode 0");
  }
  if (digitalRead(7) == LOW) {
    mode = 1;
    Serial.println("mode 1");
  }
}

void distanceDisplaySetup() {
  tft.fillScreen(ST7735_GREEN);                 //Green Border (background)
  tft.fillRect(2, 2, 156, 76, ST7735_BLACK);    //Fill rest w/Black
  tft.setTextColor(ST7735_YELLOW, ST7735_BLACK);
  tft.setCursor(52, 4);
  tft.setTextSize(2);
  tft.print("Feet:");
  tft.setTextSize(5);
  tft.drawLine(27, 20, 132, 20, ST7735_GREEN);  //Line under "Inches:"
  tft.drawLine(26, 2, 26, 77, ST7735_GREEN);
  tft.drawLine(133, 2, 133, 77, ST7735_GREEN);
  tft.setTextColor(ST7735_RED, ST7735_BLACK);
  ranDistanceSetup = true;
  ranIdleSetup = false;
  showFirstBattLevel = false;
}

int inchmap = 0;
int inchmapchangevalue = 0;

void distanceDisplay() {
  if (ranDistanceSetup == false) {
    distanceDisplaySetup();
  }

  float inchAverage = 0;
  for (int i = 1; i < 10; i++) {
    inchAverage += sonar.ping_in();
  }
  float inch = (inchAverage / 10) * 100;
  float feet = (inch / 12) / 100;
  inchmap = map(inch, 0, 12000, 1, 75);
  inchmap = constrain(inchmap, 1, 75);
  if (inchmapchangevalue != inchmap) {
    tft.fillRect(2, 2, 23, 75, ST7735_RED);
    tft.fillRect(134, 2, 23, 75, ST7735_RED);
    tft.fillRect(2, 2, 23, inchmap, ST7735_BLACK);
    tft.fillRect(134, 2, 23, inchmap, ST7735_BLACK);
    tft.drawFloat(feet, 1, 36, 32);
    inchmapchangevalue = inchmap;
  }

  if (inch <= 1200 && inch > 1) {
    fastBeep();
  }

  if (inch <= 3600 && inch > 1200) {
    medBeep();
  }

  if (inch <= 7200 && inch > 3600) {
    slowBeep();
  }

  else {
    for (int x = 0; x < 50; x++) {
      delay(1);
    }
  }
}

unsigned int x = 57;
unsigned int y = 16;

void idleDisplaySetup() {
  buzzer.off();
  tft.fillScreen(ST7735_BLACK);
  tft.drawBitmap(x, y, flag, 48, 48, ST7735_RED);
  tft.setTextSize(1);
  tft.setTextColor(ST7735_YELLOW, ST7735_BLACK);
  ranIdleSetup = true;
  ranDistanceSetup = false;
}

unsigned int battLevel = 0;
unsigned int battLevelChange = 0;
unsigned int battUpdateInterval = 2000;
unsigned long previousMillis = 0;

void idleDisplay() {
  if (ranIdleSetup == false) {
    idleDisplaySetup();
  }
  unsigned int battAdcAverage = 0;
  for (int i = 1; i < 10; i++) {
    battAdcAverage += analogRead(battLevelPin);
  }
  unsigned int battAdcReading = (battAdcAverage / 10);
  unsigned int battLevel = map(battAdcReading, 640, 740, 0, 10);
  battLevel = constrain(battLevel, 0, 10);
  if (showFirstBattLevel == false) {
    tft.drawNumber(battAdcReading, 10, 40);
    tft.drawNumber(battLevel, 120, 40);
    showFirstBattLevel = true;
  }
  if (battLevelChange != battLevel) {
    unsigned long currentMillis = millis();
    if ((unsigned long)(currentMillis - previousMillis) >= battUpdateInterval) {
      previousMillis = currentMillis;
      tft.setCursor(10, 40);
      tft.print("     ");
      tft.setCursor(120, 40);
      tft.print("     ");
      tft.drawNumber(battAdcReading, 10, 40);
      tft.drawNumber(battLevel, 120, 40);
    }


  }
  battLevelChange = battLevel;

}

unsigned long slowinterval = 300;
unsigned long medinterval = 150;
unsigned long fastinterval = 75;

bool buzzerState = false;

void slowBeep() {
  unsigned long currentMillis = millis();
  if ((unsigned long)(currentMillis - previousMillis) >= slowinterval) {
    previousMillis = currentMillis;
    if (buzzerState == false) {
      buzzerState = true;
    }
    else {
      buzzerState = false;
    }
    if (buzzerState == true) {
      buzzer.on();
    }
    if (buzzerState == false) {
      buzzer.off();
    }
  }
}
void medBeep() {
  unsigned long currentMillis = millis();
  if ((unsigned long)(currentMillis - previousMillis) >= medinterval) {
    previousMillis = currentMillis;
    if (buzzerState == false) {
      buzzerState = true;
    }
    else {
      buzzerState = false;
    }
    if (buzzerState == true) {
      buzzer.on();
    }
    if (buzzerState == false) {
      buzzer.off();
    }
  }
}

void fastBeep() {
  unsigned long currentMillis = millis();
  if ((unsigned long)(currentMillis - previousMillis) >= fastinterval) {
    previousMillis = currentMillis;
    if (buzzerState == false) {
      buzzerState = true;
    }
    else {
      buzzerState = false;
    }
    if (buzzerState == true) {
      buzzer.on();
    }
    if (buzzerState == false) {
      buzzer.off();
    }
  }
}
 
Yes, it might help if you put up the whole sketch that we can build. Right now can only guess, what is going on.
 
View attachment SimpleBackupAlarmTeensy.zip

Here is a .zip folder with the whole project folder. And no, I guess it does it when running off USB also.. I was just trying to maybe suggest that I could have a wiring issue with how I wired the VUSB and battery to the breadboard, I am not super good at schematics or visualizing my circuits yet.. but the project is currently running from the battery (3.85V now) and has been for almost a half hour, and hasn't crashed or froze yet.. so I am still grasping at straws here. Sometimes the project freezes immediately after powering it on.. the OLED doesn't even run its initialization. Other times it'll get past the setup and freeze a second or 2 into the default idleDisplay mode/function.
 
Are you certain your teensy is freezing or just your display?... perhaps put a debug led to blink. Use onboard one if the pin is free.

I think I noticed your averaging 9 battery voltage values instead of all 10. Not anything todo with your freezing issue though. though..
 
I've encountered similar mysterious freezes in a T4.0 project (that guitar effect thing), and found out the freezes do not occur any more if I leave out these allocations of temporary variables
Code:
  for (int i =
and use globally valid and predefined variables int i = 0 instead.

My totally uneducated guess is that memory on heap gets allocated for the int i but not freed after the for is exited and it does not get reused for another int i, so after some time the heap collides with the stack. But as said, totally uneducated, as I come from the old days of assembler and am not a modern coder at all, although I try to learn.

I usually follow an old rule, one name, one allocate, eternal use, universal scope. If following this, avoiding dynamic allocations, the program runs for weeks. With dynamic allocations, the program crashes after some time.
 
In many cases like this I assume Power issues...

It is hard for me to see in your photos how the voltages are fed in the circuit.

I see on the breadboard the top and bottom rails.
The plus RED on top looks like it goes through diode to VUSB. Looks like the bottom RED is VIN.
Looks like the slide switches maybe connects in external power? Looks like really thin wires. Also going through several jumpers...

So wondering if maybe with things like Ping and display and speaker, if you are getting some brownouts... Maybe just at threashold of some of the things like the display working.
 
Made up a new Fritzing project to more easily show my wiring.

I figured there may be some difficulty seeing my wiring, so I have made the breadboard project on Fritzing again. The only issue, is that I cannot find the OLED clone I used, and the Adafruit one has different pins. So I have overlayed a 50% transparent image of my clone display onto the Fritzing photo using photoshop:

BackupAlarmFritzOLED.jpg

I hope it is readable enough, now.

As for being certain Teensy is actually freezing; yes, I am pretty certain. The built-in LED on my Teensy 3.2 already blinks every time it returns to the main loop, correct? At least that's the behaviour I seem to have observed. When it freezes, sometimes the image remains on the display, but the Teensy LED stops blinking, and the buttons to switch modes do nothing. Eventually the frozen image will blank out and sometimes the program will attempt to restart, but is never successful; It will blank out after the restart attempt. The strange thing is, after freezing/blanking out, successive attempts to power cycle the device are usually ineffective. It will power back on and just show the lit-up, but blank, screen. No blinking from the Teensy LED.

Here is a video of it running my code as expected:


And another after it had frozen and I shut it down:

 
Last edited:
Deleted User, I understand that I should be minimizing the heap usage, but am too new at coding to follow your "old rule" without maybe seeing a full example of it being implemented, do you have a project of your own that I could take a peek at? I honestly just started feeling comfortable with writing these kind of "for" loops that stop at a certain number of loops. So, no idea how to replace them with something else, yet.
 
Perhaps your code hangs if your display stops communicating. I don’t know if the library works like that.. you could pull some wires out and check this.
Put some serial debug messages in setup(). When it starts doing it’s freezing thing see if you can narrow it down to a section of code.

I don’t see pull-up resistors on the i2c lines.

That’s how I’d go about this anyway.
 
Okay, I will try adding some debug code to it. But i dont understand, which pins are you referring to? Pins 16-19? Of those, pin 16 is the Trig pin of ultrasonic sensor, and pin 19 is the Echo pin. Why would I need pullup resistors? The sensor readings seem to work fine. Are you suggesting interference or something caused by not adding these pullup resistors? And dont all teensy pins already have pullup resistors?
 
Your pic shows i2c display. Teensy advice is to use external pull-ups. Your code shows spi so i don’t think you need them.
Either way, thinking about it,I don’t think your program would care if there was an issue with the screen.
 
Deleted User, I understand that I should be minimizing the heap usage, but am too new at coding to follow your "old rule" without maybe seeing a full example of it being implemented, do you have a project of your own that I could take a peek at? I honestly just started feeling comfortable with writing these kind of "for" loops that stop at a certain number of loops. So, no idea how to replace them with something else, yet.

Just declare the variable before
Code:
void setup() {
by writing it so
Code:
int i = 0;

void setup() {
and instead of declaring a local variable "i"
Code:
  for (int i = 1; i < 10; i++) {
    battAdcAverage += analogRead(battLevelPin);
  }
just reuse the globally declared "i" by leaving out the "int"
Code:
  for (i = 1; i < 10; i++) {
    battAdcAverage += analogRead(battLevelPin);
  }

That is an example.

By the way:
Logically these local variables should be unallocated after the local scope is left, in this example, the "for {}", but this is suboptimal, because if an other heap allocation happened on top of the to-be-unallocated one, this will be leaving an empty spot that does not get reused later on.
For this reason, some kind of heap-crushing or defragmentation has to happen, but I do not know, if and when this is in Teensyduino.
I just see the symptoms that this style of coding makes programs more unreliable.
There is a dependency on the linker-compiler toolchain how this solves the logical memory handling. Better not to depend on that and keep a bit of old-school.
 
Ahh okay, so this clone display is actually built for SPI mode only, doesn't even have a way to switch it on the back here:

20200607_115845.jpg
 
Deleted User, I was overthinking your advice. I understand setting it as a global variable first, and then reusing the same one in each seperate function that requires it. Thanks!
 
Looking at the board of the display, I see many possibilities for intermittent short circuits at the "solder" of the flex.

This looks gruesome!

Apply a neutral flux and touch it up with a nice tip.

Edith: I see, a part of copper already delaminated from the board, near pins 1 to 4 on the flex. Also, the maker of the board is not sure about SPI or I2C, the pin names are I2C, but the board is called SPI? Also, the delaminated part could have been GND to some pins of the flex, configuring the bus mode, which is now deranged. A close look at the datasheet could give information about that.
 
Last edited:
personally I don't like the idea of using global values like mentioned above, especially ones named like the above (i)... This can lead to real screwy issues.
Like:

Code:
int i;

void subfunc() {
    i = 0;
}

void loop() {
   for(i = 0; i < 10; i++) {
      subfunc();
}
That for loop in loop will never exit, as the i will be continuously reset back to zero. Now this is a nonsense code. There are many coding standards out there that try to restrict the use of globals. Example ROS (http://wiki.ros.org/CppStyleGuide#Global_variables) Note: globals never go out of scope, so they will always take up space in your sketch.

In general terms, the RAM memory of the processor will be assigned three different ways:
a) Globals - Both initialized and uninitialized variables. Again this is for all of the stuff that is allocated by you or system code and libraries. This is the size that you see printed out at the end of a build.

b) Just above the globals is the the Heap space (Note on T4.x, it is at different location) also I am ignoring some things like DMAMEM variables here... Things are allocated from this space by operations, like if you should call malloc or do a new operation on some object. As more things are allocated the top of the heap will keep moving up in memory.

c) Stack space - This will start at the top of memory and as you call things, this space is allocated going down. When you call a function, space will be allocated on the stack, which includes saving registers, maybe parameters passed, and any local variables used by that function. As you call more and more things, the stack will grow down. When you leave a function, that memory is no longer allocated to the values used by the function and the stack pointer goes back up....

Sometimes the difficulty of b) and c) is they grow toward each other and if they should collide then you can end up with real screwy results. This can happen when you do things like:
uint8_t *my_buf = malloc(100);
and never free it and then call can and allocate another 100... After time these leaks can cause your heap to continue to grow until finally you get strange results. Which is why many people use coding standards of never using heap... (no malloc, no new...)..

I did not see any of this in your code when I looked earlier. Sometimes it can be hidden like using a string class if there are bugs in the class...

Note: I probably have a few similar like displays that have the confusing labeling of pin names. If it is configured for SPI, SCL-> Is the clock so for default SPI would be pin 15, SDA is the data line (MOSI) on default SPI would be pin 11.


Hope that helps
 
personally I don't like the idea of using global values like mentioned above, especially ones named like the above (i)... This can lead to real screwy issues.
Like:

Code:
int i;

void subfunc() {
    i = 0;
}

void loop() {
   for(i = 0; i < 10; i++) {
      subfunc();
}
That for loop in loop will never exit, as the i will be continuously reset back to zero. Now this is a nonsense code. There are many coding standards out there that try to restrict the use of globals. Example ROS (http://wiki.ros.org/CppStyleGuide#Global_variables) Note: globals never go out of scope, so they will always take up space in your sketch.


"Eternal use" is the logical opposite of "re-use wherever".

One disposable variable is for one function only (considering loop as a function as well, which is logical), it must not be reused in other functions, but only may be used on that single one (eternal use) and may only be reused in that function sequencially, but not in nested sub sequence.

This is also important so properly instantiate linked libraries, so the variables declared there get the prefix, distinguishing them from other declarations. "myfunction mylibrary" makes a "myfuction.i", where that "i" has been declared within that library ("mylibrary"). Names mentioned are examples only.
"myotherfunction mylibrary" so another "i" gets that prefix and exists as a "myotherfunction.i", without interfering the global "i".

Sorry, english is not my native language.

At the end this is more efficient, because for the example of the "for", the program uses one word of memory forever, instead of making new allocations everytime it runs the for.
If leaving a function forever, like the function of "setup", all known disposable variables could be reused, because logically, "loop" is the sequence of "setup", so the eternal use is not violated.
 
Last edited:
At the end this is more efficient, because for the example of the "for", the program uses one word of memory forever, instead of making new allocations everytime it runs the for.
If leaving a function forever, like the function of "setup", all known disposable variables could be reused, because logically, "loop" is the sequence of "setup", so the eternal use is not violated.
Code:
for (int i = 1; i < 10; i++)
There is no memory allocation (from the heap) in the for loop. The stack pointer is just decremented by 4. There is no overhead or possibility of a leak.

Depending on the complexity of the code in the for block, with any optimisation, the compiler will probably not even need any variable and will just use a convenient register as the counter
 
Status
Not open for further replies.
Back
Top