Hi there,
i wanted to integrate an oled display to my project (ssd1306), however there seems to be a shortage of RAM by the arduino nano. I tested it with the Arduino Mega and had no problem. However, I already made the whole pcb designed for the nano.
Can you help me optimize my code, for using less ram?
/*
Setup:
1x Arduino Nano
1x OLED Display SSD1306 128×64
5x NTC_Thermistor 3950 100k Ohm
4x PWM Fan 12V
*/
// Include the library
#include <FanController.h>
#include <Thermistor.h>
#include <NTC_Thermistor.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// Fan settings
#define RPM_PIN_1 8
#define RPM_PIN_2 7
#define RPM_PIN_3 4
#define RPM_PIN_4 2
#define PWM_PIN_1 11
#define PWM_PIN_2 10
#define PWM_PIN_3 9
#define PWM_PIN_4 6
unsigned int rpm1 = 0;
unsigned int rpm2 = 0;
unsigned int rpm3 = 0;
unsigned int rpm4 = 0;
const byte dutycycle_min_fan_1 = 0;
const byte dutycycle_max_fan_1 = 100;
const byte dutycycle_min_fan_2 = 0;
const byte dutycycle_max_fan_2 = 100;
const byte dutycycle_min_fan_3 = 0;
const byte dutycycle_max_fan_3 = 100;
const byte dutycycle_min_fan_4 = 0;
const byte dutycycle_max_fan_4 = 100;
byte dutycycle_fan_1 = 0;
byte dutycycle_fan_2 = 0;
byte dutycycle_fan_3 = 0;
byte dutycycle_fan_4 = 0;
const long setfanspeed_intervall = 10000;
unsigned long previousMillis_setfanspeed = 0;
const bool set_active_fan1 = true; //fan for cooling enclosure
const bool set_active_fan2 = false; //fan for hba expander
const bool set_active_fan3 = false; //fan for hba
const bool set_active_fan4 = false; //fan for 10g nic
// Temperatur settings
#define TEMPSENSOR_PIN_1 A0
#define TEMPSENSOR_PIN_2 A1
#define TEMPSENSOR_PIN_3 A2
#define TEMPSENSOR_PIN_4 A3
#define TEMPSENSOR_PIN_5 A6
#define POTISENSOR_PIN_1 A7 //currently not used!
#define ERRORBUZZER_PIN 5
const bool set_active_tempsensor_1 = true; //temp sensor ambient, reference, before intake, should never be set false!
const bool set_active_tempsensor_2 = true; //temp sensor hdd
const bool set_active_tempsensor_3 = false; //temp sensor hba expander
const bool set_active_tempsensor_4 = false; //temp sensor hba
const bool set_active_tempsensor_5 = false; //temp sensor 10g nic
#define REFERENCE_RESISTOR 100000 // Resistance value of the resistor connected in series with the NTC
#define NOMINAL_RESISTANCE 100000 // Resistance of the NTC at nominal temperature
#define NOMINAL_TEMPERATURE 25 // Temperature at which the NTC has the specified resistance
#define B_VALUE 3950 // Beta coefficient (to be found in the NTC data sheet)
Thermistor* thermistor1;
Thermistor* thermistor2;
Thermistor* thermistor3;
Thermistor* thermistor4;
Thermistor* thermistor5;
//IMPORTANT: all temp values are in unit celsius (°C) !
double temp_0 = 0; //ambient, reference
double temp_1 = 0; //hdd
double temp_2 = 0; //hba expander
double temp_3 = 0; //hba
double temp_4 = 0; //10g nic
double temp_diff_0_1 = 0; //= temp_1 - temp_0
double temp_diff_0_2 = 0; //= temp_2 - temp_0
double temp_diff_0_3 = 0; //= temp_3 - temp_0
double temp_diff_0_4 = 0; //= temp_4 - temp_0
const double temp_max_0 = 37; // max temp for sensor 0 (ambient temp)
const double temp_max_1 = 36; // max temp for sensor 1 (hdd)
const double temp_max_2 = 29; // max temp for sensor 2 (hba expander)
const double temp_max_3 = 29; // max temp for sensor 3 (hba)
const double temp_max_4 = 29; // max temp for sensor 4 (10g nic)
//double temp_diff_max_1_1 = 0; //= temp_max_1 - temp_1
//double temp_diff_max_2_2 = 0; //= temp_max_2 - temp_2
//double temp_diff_max_3_3 = 0; //= temp_max_3 - temp_3
//double temp_diff_max_4_4 = 0; //= temp_max_4 - temp_4
const double temp_diff_0_1_max = 5; // max temp difference between sensor 0 (ambient, reference) and sensor 1 (hdd)
const double temp_diff_0_2_max = 5; // max temp difference between sensor 0 (ambient, reference) and sensor 2 (hba expander)
const double temp_diff_0_3_max = 5; // max temp difference between sensor 0 (ambient, reference) and sensor 3 (hba)
const double temp_diff_0_4_max = 5; // max temp difference between sensor 0 (ambient, reference) and sensor 4 (10g nic)
const double valid_temp_min = 0;
const double valid_temp_max = 100;
//error codes
const byte errorcode_temp_sensor = 10;
const double map_factor = 1000; //factor for elimintaing rounding errors for small values of double class
// Choose a threshold in milliseconds between readings.
// A smaller value will give more updated results,
// while a higher value will give more accurate and smooth readings
#define SENSOR_THRESHOLD 1000
bool debug = true; //enables debug mode, when set true
bool buzzer_active = false; //enables buzzer, when set true
// Initialize library
FanController fan1(RPM_PIN_1, SENSOR_THRESHOLD, PWM_PIN_1);
FanController fan2(RPM_PIN_2, SENSOR_THRESHOLD, PWM_PIN_2);
FanController fan3(RPM_PIN_3, SENSOR_THRESHOLD, PWM_PIN_3);
FanController fan4(RPM_PIN_4, SENSOR_THRESHOLD, PWM_PIN_4);
// Display SETTINGS
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
const long displayrefreshintervall = 500;
unsigned long previousMillis_displayrefresh = 0;
String display_status_message = "NaN";
void getfanspeed(void) {
// Call fan.getSpeed() to get fan RPM
if (set_active_fan1) {
rpm1 = fan1.getSpeed();
}
if (set_active_fan2) {
rpm2 = fan2.getSpeed();
}
if (set_active_fan3) {
rpm3 = fan3.getSpeed();
}
if (set_active_fan4) {
rpm4 = fan4.getSpeed();
}
if (debug) {
if (set_active_fan1) {
Serial.print("Current speed fan1: ");
Serial.print(rpm1);
Serial.println(" RPM");
}
if (set_active_fan2) {
Serial.print("Current speed fan2: ");
Serial.print(rpm2);
Serial.println(" RPM");
}
if (set_active_fan3) {
Serial.print("Current speed fan3: ");
Serial.print(rpm3);
Serial.println(" RPM");
}
if (set_active_fan4) {
Serial.print("Current speed fan4: ");
Serial.print(rpm4);
Serial.println(" RPM");
}
}
}
void gettemp(void) {
for (int i = 0; i <= 999; i++) {
if (set_active_tempsensor_1) {
temp_0 = temp_0 + thermistor1->readCelsius();
}
if (set_active_tempsensor_2) {
temp_1 = temp_1 + thermistor2->readCelsius();
}
if (set_active_tempsensor_3) {
temp_2 = temp_2 + thermistor3->readCelsius();
}
if (set_active_tempsensor_4) {
temp_3 = temp_3 + thermistor4->readCelsius();
}
if (set_active_tempsensor_5) {
temp_4 = temp_4 + thermistor5->readCelsius();
}
}
if (set_active_tempsensor_1) {
temp_0 = temp_0 / 1000;
}
if (set_active_tempsensor_2) {
temp_1 = temp_1 / 1000;
//temp_diff_max_1_1 = abs(temp_max_1 - temp_1);
}
if (set_active_tempsensor_3) {
temp_2 = temp_2 / 1000;
//temp_diff_max_2_2 = abs(temp_max_2 - temp_2);
}
if (set_active_tempsensor_4) {
temp_3 = temp_3 / 1000;
//temp_diff_max_3_3 = abs(temp_max_3 - temp_3);
}
if (set_active_tempsensor_5) {
temp_4 = temp_4 / 1000;
//temp_diff_max_4_4 = abs(temp_max_4 - temp_4);
}
if (set_active_tempsensor_1 && set_active_tempsensor_2) {
temp_diff_0_1 = abs(temp_1 - temp_0);
}
if (set_active_tempsensor_1 && set_active_tempsensor_3) {
temp_diff_0_1 = abs(temp_2 - temp_0);
}
if (set_active_tempsensor_1 && set_active_tempsensor_4) {
temp_diff_0_1 = abs(temp_3 - temp_0);
}
if (set_active_tempsensor_1 && set_active_tempsensor_5) {
temp_diff_0_1 = abs(temp_4 - temp_0);
}
if (debug) {
if (set_active_tempsensor_1) {
Serial.print("Temperatur1: ");
Serial.print(temp_0);
Serial.println(" °C ");
}
if (set_active_tempsensor_2) {
Serial.print("Temperatur2: ");
Serial.print(temp_1);
Serial.println(" °C ");
}
if (set_active_tempsensor_3) {
Serial.print("Temperatur3: ");
Serial.print(temp_2);
Serial.println(" °C ");
}
if (set_active_tempsensor_4) {
Serial.print("Temperatur4: ");
Serial.print(temp_3);
Serial.println(" °C ");
}
if (set_active_tempsensor_5) {
Serial.print("Temperatur5: ");
Serial.print(temp_4);
Serial.println(" °C");
}
delay(100);
}
}
void setfanspeed(void) {
if (validatetempsensors()) { //check, if each temp sensor is within valid_temp_min and valid_temp_max (only when set_active_tempsensor_X = true)
unsigned long currentMillis = millis();
display_status_message = "normal operation";
if (currentMillis - previousMillis_setfanspeed >= setfanspeed_intervall) { // check whether the last setfanspeed() run was more than setfanspeed_intervall ago
previousMillis_setfanspeed = currentMillis;
// fan1
if (set_active_fan1) {
if (temp_1 > temp_max_1 || temp_diff_0_1 > temp_diff_0_1_max) { //check, if the temp is out of limits
display_status_message = "hdd temp critical!";
fan1.setDutyCycle(dutycycle_max_fan_1);
if (debug) {
Serial.print("fan1 duty cycle set at max (");
Serial.print(dutycycle_max_fan_1);
Serial.println(")");
}
} else {
double temp_factored_0 = map_factor * temp_0;
double temp_factored_1 = map_factor * temp_1;
double temp_diff_factored_0_1 = map_factor * temp_diff_0_1;
double temp_diff_factored_0_1_max = map_factor * temp_diff_0_1_max;
double temp_factored_max_1 = map_factor * temp_max_1;
long dutycycle_fan_1 = 0;
if (debug) {
Serial.print("temp_0 = ");
Serial.println(temp_0);
Serial.print("temp_1 = ");
Serial.println(temp_1);
Serial.print("temp_diff_0_1 = ");
Serial.println(temp_diff_0_1);
Serial.print("temp_diff_0_1_max = ");
Serial.println(temp_diff_0_1_max);
Serial.print("temp_max_1 = ");
Serial.println(temp_max_1);
delay(10000);
}
if (temp_factored_max_1 - temp_factored_1 >= temp_diff_factored_0_1_max - temp_diff_factored_0_1) {
dutycycle_fan_1 = map(temp_diff_factored_0_1, 0, temp_diff_factored_0_1_max, dutycycle_min_fan_1, dutycycle_max_fan_1);
if (debug) {
Serial.println("A");
Serial.println("(temp_factored_max_1 - temp_factored_1 >= temp_diff_factored_0_1_max - temp_diff_factored_0_1");
}
} else {
dutycycle_fan_1 = map(temp_factored_1, temp_factored_0, temp_factored_max_1, dutycycle_min_fan_1, dutycycle_max_fan_1);
if (debug) {
Serial.println("B");
Serial.println("(temp_factored_max_1 - temp_factored_1 < temp_diff_factored_0_1_max - temp_diff_factored_0_1");
}
}
fan1.setDutyCycle(dutycycle_fan_1);
if (debug) {
Serial.print("fan1 duty cycle set at ");
Serial.print(dutycycle_fan_1);
Serial.println(" ");
}
/*
if (temp_diff_0_1 >= temp_diff_max_1_1) {
// control fan1 based on the temperature difference between (temp_max_1 and temp_1 = temp_diff_max_1_1)
// ################# HIER WEITER #################
byte dutycycle_fan_1 = map(temp_diff_0_1, 0, temp_diff_0_1_max, dutycycle_min_fan_1, dutycycle_max_fan_1);
fan1.setDutyCycle(dutycycle_fan_1);
if (debug) {
Serial.print("fan1 duty cycle set at ");
Serial.print(dutycycle_fan_1);
Serial.println(" ");
}
} else {
byte dutycycle_fan_1 = map(temp_diff_0_1, 0, temp_diff_0_1_max, dutycycle_min_fan_1, dutycycle_max_fan_1);
fan1.setDutyCycle(dutycycle_fan_1);
if (debug) {
Serial.print("fan1 duty cycle set at ");
Serial.print(dutycycle_fan_1);
Serial.println(" ");
}
}*/
}
}
}
} else {
display_status_message = "temp sensor error";
setfanspeedmax();
}
}
void setfanspeedatboot(void) {
display_status_message = "booting";
if (set_active_fan1) {
fan1.setDutyCycle(dutycycle_max_fan_1);
}
if (set_active_fan2) {
fan2.setDutyCycle(dutycycle_max_fan_2);
}
if (set_active_fan3) {
fan3.setDutyCycle(dutycycle_max_fan_3);
}
if (set_active_fan4) {
fan4.setDutyCycle(dutycycle_max_fan_4);
}
if (debug) {
Serial.println("all fans at max speed");
}
delay(500);
if (set_active_fan1) {
fan1.setDutyCycle(dutycycle_min_fan_1);
}
if (set_active_fan2) {
fan2.setDutyCycle(dutycycle_min_fan_2);
}
if (set_active_fan3) {
fan3.setDutyCycle(dutycycle_min_fan_3);
}
if (set_active_fan4) {
fan4.setDutyCycle(dutycycle_min_fan_4);
}
if (debug) {
Serial.println("all fans at min speed");
}
}
void setfanspeedmax(void) {
if (set_active_fan1) {
fan1.setDutyCycle(dutycycle_max_fan_1);
}
if (set_active_fan2) {
fan2.setDutyCycle(dutycycle_max_fan_2);
}
if (set_active_fan3) {
fan3.setDutyCycle(dutycycle_max_fan_3);
}
if (set_active_fan4) {
fan4.setDutyCycle(dutycycle_max_fan_4);
}
if (debug) {
Serial.println("all fans at max speed");
}
}
bool validatetempsensors(void) {
if (set_active_tempsensor_1) {
if (temp_0 > valid_temp_min && temp_0 < temp_max_0) { //check sensor 0; attention: max temp for temp_0 is temp_max_0 not valid_temp_max (due to uninfluenceable ambient temp by fans)!
} else {
if (debug) {
Serial.println("Sensortemp 0 critical!");
}
errorbuzzer(errorcode_temp_sensor);
return false;
}
}
if (set_active_tempsensor_2) {
if (temp_1 > valid_temp_min && temp_1 < valid_temp_max) { //check sensor 1
} else {
if (debug) {
Serial.println("Sensortemp 1 critical!");
}
errorbuzzer(errorcode_temp_sensor);
return false;
}
}
if (set_active_tempsensor_3) {
if (temp_2 > valid_temp_min && temp_2 < valid_temp_max) { //check sensor 2
} else {
if (debug) {
Serial.println("Sensortemp 2 critical!");
}
errorbuzzer(errorcode_temp_sensor);
return false;
}
}
if (set_active_tempsensor_4) {
if (temp_3 > valid_temp_min && temp_3 < valid_temp_max) { //check sensor 3
} else {
if (debug) {
Serial.println("Sensortemp 3 critical!");
}
errorbuzzer(errorcode_temp_sensor);
return false;
}
}
if (set_active_tempsensor_5) {
if (temp_4 > valid_temp_min && temp_4 < valid_temp_max) { //check sensor 4
} else {
if (debug) {
Serial.println("Sensortemp 4 critical!");
}
errorbuzzer(errorcode_temp_sensor);
return false;
}
}
if (debug) {
Serial.println("All Sensortemps are uncritical");
}
return true;
}
void errorbuzzer(byte errorcode) {
if (buzzer_active) {
switch (errorcode) {
case errorcode_temp_sensor: // validatetempsensors = false
tone(ERRORBUZZER_PIN, 5);
delay(50);
noTone(ERRORBUZZER_PIN);
break;
default:
// Statement(s)
break;
}
}
}
void initiate_display() {
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;)
; // Don't proceed, loop forever
}
display.display();
delay(20);
// Clear the buffer
display.clearDisplay();
delay(20);
display.setTextColor(SSD1306_WHITE); // Draw white text
display.cp437(true);
display.setTextSize(1);
}
void update_display() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis_displayrefresh >= displayrefreshintervall) { // check whether the last setfanspeed() run was more than setfanspeed_intervall ago
previousMillis_displayrefresh = currentMillis;
display.clearDisplay();
display.setCursor(0, 0);
display.print("Temp ");
display.write(0xF8);
display.println("C");
display.print("Ambient ");
display.println(temp_0);
display.print("HDD ");
display.println(temp_1);
display.print("HBA Ex. ");
display.println(temp_2);
display.print("HBA ");
display.println(temp_3);
display.print("10g NIC ");
display.println(temp_4);
display.setCursor(62, 0);
display.print("Cycle %");
display.println(" RPM");
display.setCursor(62, 16);
display.print("Fan1 ");
display.print(dutycycle_fan_1);
display.print(" ");
display.println(rpm1);
display.setCursor(62, 24);
display.print("Fan2 ");
display.print(dutycycle_fan_2);
display.print(" ");
display.println(rpm2);
display.setCursor(62, 32);
display.print("Fan3 ");
display.print(dutycycle_fan_3);
display.print(" ");
display.println(rpm3);
display.setCursor(62, 40);
display.print("Fan4 ");
display.print(dutycycle_fan_4);
display.print(" ");
display.println(rpm4);
display.println("Status: ");
display.print(display_status_message);
display.display();
}
}
void setup(void) {
// start serial port
Serial.begin(9600);
initiate_display();
pinMode(TEMPSENSOR_PIN_1, INPUT_PULLUP);
pinMode(TEMPSENSOR_PIN_2, INPUT_PULLUP);
pinMode(TEMPSENSOR_PIN_3, INPUT_PULLUP);
pinMode(TEMPSENSOR_PIN_4, INPUT_PULLUP);
pinMode(TEMPSENSOR_PIN_5, INPUT_PULLUP);
// Start up the library
fan1.begin();
fan2.begin();
fan3.begin();
fan4.begin();
//initiate temp sensors
thermistor1 = new NTC_Thermistor(TEMPSENSOR_PIN_1, REFERENCE_RESISTOR, NOMINAL_RESISTANCE, NOMINAL_TEMPERATURE, B_VALUE);
thermistor2 = new NTC_Thermistor(TEMPSENSOR_PIN_2, REFERENCE_RESISTOR, NOMINAL_RESISTANCE, NOMINAL_TEMPERATURE, B_VALUE);
thermistor3 = new NTC_Thermistor(TEMPSENSOR_PIN_3, REFERENCE_RESISTOR, NOMINAL_RESISTANCE, NOMINAL_TEMPERATURE, B_VALUE);
thermistor4 = new NTC_Thermistor(TEMPSENSOR_PIN_4, REFERENCE_RESISTOR, NOMINAL_RESISTANCE, NOMINAL_TEMPERATURE, B_VALUE);
thermistor5 = new NTC_Thermistor(TEMPSENSOR_PIN_5, REFERENCE_RESISTOR, NOMINAL_RESISTANCE, NOMINAL_TEMPERATURE, B_VALUE);
setfanspeedatboot();
}
void loop(void) {
gettemp();
getfanspeed();
setfanspeed();
update_display();
}