From 737c6c3b358dbfef9ee6fcc3b85b06755bb00f9e Mon Sep 17 00:00:00 2001 From: -help Date: Fri, 26 Jan 2024 00:42:39 +0200 Subject: [PATCH] first commit --- .gitignore | 5 + .vscode/extensions.json | 10 ++ include/README | 39 +++++ lib/README | 46 ++++++ platformio.ini | 31 ++++ src/Tools/AnalogRef.h | 91 +++++++++++ src/Tools/Thermistor.cpp | 85 ++++++++++ src/Tools/Thermistor.h | 73 +++++++++ src/main.cpp | 325 +++++++++++++++++++++++++++++++++++++++ test/README | 11 ++ 10 files changed, 716 insertions(+) create mode 100644 .gitignore create mode 100644 .vscode/extensions.json create mode 100644 include/README create mode 100644 lib/README create mode 100644 platformio.ini create mode 100644 src/Tools/AnalogRef.h create mode 100644 src/Tools/Thermistor.cpp create mode 100644 src/Tools/Thermistor.h create mode 100644 src/main.cpp create mode 100644 test/README diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..080e70d --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ], + "unwantedRecommendations": [ + "ms-vscode.cpptools-extension-pack" + ] +} diff --git a/include/README b/include/README new file mode 100644 index 0000000..194dcd4 --- /dev/null +++ b/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/lib/README b/lib/README new file mode 100644 index 0000000..6debab1 --- /dev/null +++ b/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in a an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..d98b08a --- /dev/null +++ b/platformio.ini @@ -0,0 +1,31 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:ATmega4809] +platform = atmelmegaavr +board = ATmega4809 +framework = arduino + +upload_speed = 115200 +board_hardware.uart = uart0 +upload_protocol = arduino +lib_ldf_mode = chain+ +; change MCU frequency +board_build.f_cpu = 16000000L + +lib_deps = + adafruit/Adafruit GFX Library@^1.11.5 + adafruit/Adafruit ST7735 and ST7789 Library@^1.10.0 + https://github.com/adafruit/Adafruit_BusIO.git + SPI + Wire + https://github.com/PowerBroker2/ArduPID.git + https://github.com/PowerBroker2/FireTimer.git + https://github.com/adafruit/Adafruit_SSD1306.git diff --git a/src/Tools/AnalogRef.h b/src/Tools/AnalogRef.h new file mode 100644 index 0000000..94c6909 --- /dev/null +++ b/src/Tools/AnalogRef.h @@ -0,0 +1,91 @@ + +#ifndef ANALOGREF_H +#define ANALOGREF_H + +#include + +class AnalogRef +{ +private: + float systemVoltage; // Reference voltage in volts + + boolean systemVolatgeBelow4_5V = false; + uint8_t voltageRefPin = 27; + + uint8_t voltageInPin = 28; + +public: + float sysVoltage; + float sysMultiplyer; + float outputVoltage; + float outputVoltageMultiplyer; + float differenceMultiplyer; + AnalogRef(float systemVoltage) + { + this->systemVoltage = systemVoltage; + } + + float calculateSystemVoltage() + { + const uint8_t sampleCount = 1; + + uint16_t rawValue = 0; + + for (size_t i = 0; i < sampleCount; ++i) + { + rawValue += analogRead(voltageRefPin); + } + + const float voltageRef = 1023.0; + const float systemVoltage = 5.0; + const float systemVoltageOut = rawValue / sampleCount * systemVoltage / voltageRef; + const float voltage5V = 2.5 / systemVoltageOut * systemVoltage; + + systemVolatgeBelow4_5V = voltage5V < 4.5; + + return voltage5V; + } + + float calculateSystemVoltageMultyplyer() + { + + // Calculate the actual 5V system voltage + float currentSystemVoltage = calculateSystemVoltage(); + + // Calculate the actual 5V system voltage + float voltage_5V_multiplyer = (5 / currentSystemVoltage); + + return voltage_5V_multiplyer; + } + + float calculateInputVoltage() + { + + calculateSystemVoltage(); + + float value; + + uint8_t sampleCount = 20; + value = 0; + + for (size_t i = 0; i < sampleCount; ++i) + { + value += analogRead(voltageInPin); + } + + value /= sampleCount; + + float vOut = (value * systemVoltage) / 1024.0; + + return vOut * 5.8; + } + + void calculate() + { + + sysVoltage = calculateSystemVoltage(); + sysMultiplyer = 5 / sysVoltage; + } +}; + +#endif // ANALOGREF_H diff --git a/src/Tools/Thermistor.cpp b/src/Tools/Thermistor.cpp new file mode 100644 index 0000000..4b7552d --- /dev/null +++ b/src/Tools/Thermistor.cpp @@ -0,0 +1,85 @@ +#include "Thermistor.h" + +Thermistor::Thermistor() +{ +} + +Thermistor::Thermistor(uint8_t pin, float resistance, TempCalibration calibration) +{ + + thermistorPin = pin; + setRes = resistance; + + calculateCoefficents(resistance, calibration); +} + +Thermistor::~Thermistor() +{ +} + +int Thermistor::getTemperature() +{ + + // Get an average of 5 readings + int temp = 0; + + uint8_t samples = 5; + for (int i = 0; i < samples; i++) + { + getResistance(); + temp += (int)1 / (coefficents.a + coefficents.b * log(sensorResistance) + coefficents.c * (pow(log(sensorResistance), 3))) - K; + } + + temp = temp / samples; + + + return temp; +} + +void Thermistor::calculateCoefficents(float resistance, TempCalibration calibration) +{ + + float lowK = calibration.lowC + K; + float midK = calibration.midC + K; + float highK = calibration.highC + K; + + float lowLnr = log(calibration.lowR); + float midLnr = log(calibration.midR); + float highLnr = log(calibration.highR); + + float ln1 = lowLnr - midLnr; + float ln2 = lowLnr - highLnr; + float t1 = (1 / lowK) - (1 / midK); + float t2 = (1 / lowK) - (1 / highK); + + float c = (t1 - ln1 * t2 / ln2) / ((pow(lowLnr, 3) - pow(midLnr, 3)) - ln1 * (pow(lowLnr, 3) - pow(highLnr, 3)) / ln2); + float b = (t1 - c * (pow(lowLnr, 3) - pow(midLnr, 3))) / ln1; + float a = 1 / lowK - c * pow(lowLnr, 3) - b * lowLnr; + + coefficents.a = (a); + coefficents.b = (b); + coefficents.c = (c); +} + +float Thermistor::getResistance() +{ + + analogRef.calculate(); + + float systemVoltage = analogRef.sysVoltage; + + int raw = analogRead(thermistorPin); + + // Get resistance value + float buffer = raw * systemVoltage; + float vOut = (buffer) / 1023; + // Serial.println(vOut); + buffer = (systemVoltage / vOut) - 1; + + // Serial.println(R2); + // return the resistence + + sensorResistance = setRes * buffer; + + return sensorResistance; +} diff --git a/src/Tools/Thermistor.h b/src/Tools/Thermistor.h new file mode 100644 index 0000000..8d69e32 --- /dev/null +++ b/src/Tools/Thermistor.h @@ -0,0 +1,73 @@ +#ifndef THERMISTOR_H +#define THERMISTOR_H + +#include +#include + + +#define THERMISTOR1_PIN 39 +#define THERMISTOR2_PIN 38 +#define THERMISTOR3_PIN 37 +#define THERMISTOR4_PIN 36 +#define THERMISTOR5_PIN 33 +#define THERMISTOR6_PIN 32 + +extern AnalogRef analogRef; + +// Include any necessary libraries here + +struct Coefficents +{ + float a; + float b; + float c; +}; + +struct TempCalibration +{ + float lowC; + float lowR; + float midC; + float midR; + float highC; + float highR; +}; + +class Thermistor +{ +public: + // Constructor + Thermistor(); + + Thermistor(uint8_t pin, float resistance, TempCalibration calibration); + + // Destructor + ~Thermistor(); + + // Public Methods + int getTemperature(); + float getResistance(); + + // Public Variables + +private: + + const double K = 273.15; + + float sensorResistance; + + uint8_t thermistorPin; + float setRes; + + Coefficents coefficents; + + float referenceResistance; + + void calculateCoefficents(float resistance, TempCalibration calibration); + + + + +}; + +#endif // THERMISTOR_H diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..aa19f79 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,325 @@ +#include +#include "ArduPID.h" +#include // Include the ST7789 library +#include +#include +#include +#include +#include + +enum Button +{ + UP, + DOWN, + BACK, + SELECT, + NONE +}; + +AnalogRef analogRef(5.0); + +// LED pins +#define yellowLED 18 +#define greenLED 19 +#define redLED 20 + +// Button pins +#define upButton 21 +#define downButton 22 +#define backButton 23 +#define selectButton 24 + +volatile bool upButtonPressed = false; +volatile bool downButtonPressed = false; +volatile bool backButtonPressed = false; +volatile bool selectButtonPressed = false; + +volatile bool upButtonReleased = false; +volatile bool downButtonReleased = false; +volatile bool backButtonReleased = false; +volatile bool selectButtonReleased = false; + +enum ButtonState +{ + IDLE, + PRESSED, + RELEASED +}; + +ButtonState upButtonState = IDLE; +ButtonState downButtonState = IDLE; +ButtonState backButtonState = IDLE; +ButtonState selectButtonState = IDLE; + +// LCD display pins +#define TFT_CS 7 +#define TFT_RST 12 +#define TFT_DC 14 +#define MOSI 4 // MOSI +#define SCK 6 // SCK + +// Create an instance of the Adafruit ST7789 class using the custom SPI pins +Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, MOSI, SCK, TFT_RST); + +// OLED display width and height, for a typical 128x64 display +#define SCREEN_WIDTH 128 +#define SCREEN_HEIGHT 64 + +#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) +Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); + +// Initalize a 3950 100K thermistor with 2.5k reference resistor +Thermistor thermistor1(THERMISTOR1_PIN, 2500, {25, 100000, 86, 10000, 170, 1000}); + +ArduPID PID; + +Button getPressedButton(); +Button handleButtons(); + +void upButtonISR(); +void downButtonISR(); +void backButtonISR(); +void selectButtonISR(); + +void i2cScanner(); + +void setup() +{ + + if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) + { + Serial.println(F("SSD1306 allocation failed")); + for (;;) + ; // Don't proceed further, loop forever + } + + analogWriteFrequency(64); + + display.setRotation(3); + pinMode(yellowLED, OUTPUT); + pinMode(greenLED, OUTPUT); + pinMode(redLED, OUTPUT); + + pinMode(upButton, INPUT_PULLUP); + pinMode(downButton, INPUT_PULLUP); + pinMode(backButton, INPUT_PULLUP); + pinMode(selectButton, INPUT_PULLUP); + + attachInterrupt(digitalPinToInterrupt(upButton), upButtonISR, FALLING); + attachInterrupt(digitalPinToInterrupt(downButton), downButtonISR, FALLING); + attachInterrupt(digitalPinToInterrupt(backButton), backButtonISR, FALLING); + attachInterrupt(digitalPinToInterrupt(selectButton), selectButtonISR, FALLING); + + Serial.begin(9600); + + Serial.println("Starting LCD"); + + // tft.init(240, 320); // The dimensions (width and height) of your display + + // // Set the rotation of the display if needed (0, 1, 2, or 3) + // tft.setRotation(1); + + // // Fill the screen with a background color + // tft.fillScreen(ST77XX_BLACK); + + // // Draw the lines of the gaph with 20 pixels from left side and 20 pixels from bottom just left side and bottom line using draw fast line + // tft.drawLine(30, 30, 30, 210, ST77XX_WHITE); + // tft.drawLine(30, 210, 300, 210, ST77XX_WHITE); + + // Set cursor to middle of screen and calculate center line from text vairable; + // char *text = "Reflow quickchip 138c"; + // int16_t x1, y1; + // uint16_t w, h; + + // tft.setTextSize(2); + // tft.getTextBounds(text, 0, 0, &x1, &y1, &w, &h); + // tft.setCursor(160 - (w / 2), 0 + (h / 2)); + + // // // Print text to screen + // tft.print(text); + Serial.println("Ready!"); +} + +void loop() +{ + + handleButtons(); + + analogRef.calculate(); + + float sysVoltage = analogRef.sysVoltage; + float inputVoltage = analogRef.calculateInputVoltage(); + + // Print the system voltage on the tft + + display.clearDisplay(); + Serial.print("Thermistor 1: "); + Serial.println(thermistor1.getTemperature()); + char *text = "Sys V: "; + display.setTextSize(2); + display.setTextColor(SSD1306_WHITE); + display.setCursor(0, 20); + display.println(text); + display.setCursor(0, 40); + display.println(sysVoltage); + char *text2 = "In V: "; + display.setTextSize(2); + display.setTextColor(SSD1306_WHITE); + display.setCursor(0, 60); + display.println(text2); + display.setCursor(0, 80); + display.println(inputVoltage); + char *text3 = "C:"; + display.setTextSize(2); + display.setTextColor(SSD1306_WHITE); + display.setCursor(0, 100); + display.println(text3); + display.setCursor(25, 100); + display.println(thermistor1.getTemperature()); + + display.display(); + + // Serial.println("System voltage: "); + + // Serial.print("Output voltage: "); + // Serial.println(sysVoltage); + + // Serial.print("Input voltage: "); + // Serial.println(analogRef.calculateInputVoltage()); +} + +Button getPressedButton() +{ + if (upButtonPressed) + { + upButtonPressed = false; + + return UP; + } + else if (downButtonPressed) + { + downButtonPressed = false; + + return DOWN; + } + else if (backButtonPressed) + { + backButtonPressed = false; + + return BACK; + } + else if (selectButtonPressed) + { + selectButtonPressed = false; + + return SELECT; + } + + return NONE; +} + +Button handleButtons() +{ + + Button pressedButton = getPressedButton(); + + if (pressedButton != NONE) + { + Serial.print("Button pressed: "); + switch (pressedButton) + { + case UP: + Serial.println("UP"); + digitalWrite(yellowLED, HIGH); + delay(100); + digitalWrite(yellowLED, LOW); + break; + case DOWN: + Serial.println("DOWN"); + digitalWrite(yellowLED, HIGH); + delay(100); + digitalWrite(yellowLED, LOW); + break; + case BACK: + Serial.println("BACK"); + digitalWrite(redLED, HIGH); + delay(100); + digitalWrite(redLED, LOW); + break; + case SELECT: + Serial.println("SELECT"); + analogWrite(greenLED, 20); + delay(100); + analogWrite(greenLED, 0); + + break; + default: + break; + } + } + + return pressedButton; +} + +void upButtonISR() +{ + upButtonPressed = true; +} + +void downButtonISR() +{ + downButtonPressed = true; +} + +void backButtonISR() +{ + backButtonPressed = true; +} + +void selectButtonISR() +{ + selectButtonPressed = true; +} + +void i2cScanner() +{ + + byte error, address; + int nDevices; + + Serial.println("Scanning..."); + + nDevices = 0; + for (address = 1; address < 127; address++) + { + // The i2c_scanner uses the return value of + // the Write.endTransmisstion to see if + // a device did acknowledge to the address. + Wire.beginTransmission(address); + error = Wire.endTransmission(); + + if (error == 0) + { + Serial.print("I2C device found at address 0x"); + if (address < 16) + Serial.print("0"); + Serial.print(address, HEX); + Serial.println(" !"); + + nDevices++; + } + else if (error == 4) + { + Serial.print("Unknown error at address 0x"); + if (address < 16) + Serial.print("0"); + Serial.println(address, HEX); + } + } + if (nDevices == 0) + Serial.println("No I2C devices found\n"); + else + Serial.println("done\n"); + + delay(5000); // wait 5 seconds for next scan +} \ No newline at end of file diff --git a/test/README b/test/README new file mode 100644 index 0000000..9b1e87b --- /dev/null +++ b/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PlatformIO Test Runner and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PlatformIO Unit Testing: +- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html