Skip to content

Commit

Permalink
Merge pull request #34 from balerion:SAMD-port
Browse files Browse the repository at this point in the history
SAMD-port
  • Loading branch information
balerion authored Mar 18, 2021
2 parents 02334bd + fad81ad commit bf085c6
Show file tree
Hide file tree
Showing 2 changed files with 212 additions and 55 deletions.
221 changes: 166 additions & 55 deletions Arduino code/main.ino
Original file line number Diff line number Diff line change
@@ -1,20 +1,30 @@
#include <EEPROM.h>
#include <SPI.h>
#include <U8g2lib.h>
#include <Wire.h>

#include "LowPower.h"
#include "ArduinoLowPower.h"
#include "SD.h"
#include "src/graphics.h"

// Pin definition
#define VBATPIN A9
#define VBATPIN A7
#define CHTMEASUREPIN A1
#define RPMPIN 0
#define BUTTONPIN 1
#define RPMPIN 1
#define BUTTONPIN 0
#define RPMPOWER A2
#define CHTPOWER A3

#define chipSelect 4

// uncomment this for dev mode
#define DEVMODE 1
// #define DEVMODE 1
// #define FAKERPM 1

// SAMD serial port adaptation
#if defined(ARDUINO_SAMD_ZERO) && defined(SERIAL_PORT_USBVIRTUAL)
// Required for Serial on Zero based boards
#define Serial SERIAL_PORT_USBVIRTUAL
#endif

// Battery monitoring
const float minVoltage = 3.2;
Expand All @@ -24,25 +34,26 @@ const float refVoltage = 3.3;
// defines for tacho
const float min_rpm = 2000;
const float max_rpm = 8000;
const long updatet = 20;

float rpm_filt = 0;
float ww = 2; // filter weight. larger numbers -> slower filters. 40 is ..s, 1
float ww = 3; // filter weight. larger numbers -> slower filters. 40 is ..s, 1
// is no filtering

// defines for tacho: Timer auxiliary variables
unsigned long tt = millis();
unsigned long dt = micros();
unsigned long oldtime = micros();
float rev = 0;
volatile unsigned long t0 = micros();
volatile unsigned long t1 = micros();
// volatile unsigned long oldtime = micros();
volatile float rev = 0;
float rpm = 0;

unsigned long fakerpm_dt = 0;
unsigned long fakerpm_tt = 0;

unsigned long lastTrigger = 0;
boolean startTimer = false;

// Defining the type of display used (128x32)
U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);

// Defining variables for OLED display
char displayBuffer[20];
String displayString;
Expand All @@ -56,9 +67,12 @@ bool wasSleeping = true;
bool awake = true;
float sleepInput = 0;

// time variables
// Defining the type of display used (128x32)
U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);

// time keeping variables
long tt_loop = 0;
long loopUpdateTime = 10;
long loopUpdateTime = 25;
long tt_button = 0;
long dt_button = 500;
long tt_slowdraw = 0;
Expand All @@ -68,47 +82,102 @@ unsigned long tt_running = 0;
unsigned long current_runtime = 0;
unsigned long total_runtime = 0;

long EEPROMReadlong(long address) {
long four = EEPROM.read(address);
long three = EEPROM.read(address + 1);
long two = EEPROM.read(address + 2);
long one = EEPROM.read(address + 3);

return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) +
((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
}

void EEPROMWritelong(int address, long value) {
byte four = (value & 0xFF);
byte three = ((value >> 8) & 0xFF);
byte two = ((value >> 16) & 0xFF);
byte one = ((value >> 24) & 0xFF);

EEPROM.write(address, four);
EEPROM.write(address + 1, three);
EEPROM.write(address + 2, two);
EEPROM.write(address + 3, one);
// SD card stuff
File logfile;

// blink out an error code
void error(uint8_t errno) {
while (1) {
uint8_t i;
for (i = 0; i < errno; i++) {
digitalWrite(LED_BUILTIN, HIGH);
delay(100);
digitalWrite(LED_BUILTIN, LOW);
delay(100);
}
for (i = errno; i < 10; i++) {
delay(200);
}
}
}

// sleepy function
void prepareSleep() {
u8g2.setPowerSave(1);
pinMode(RPMPOWER, INPUT);
pinMode(CHTPOWER, INPUT);
pinMode(13, INPUT);
digitalWrite(RPMPOWER, LOW);
digitalWrite(CHTPOWER, LOW);
wasSleeping = false;
EEPROMWritelong(0, total_runtime);
LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF);
logfile.println(total_runtime);
logfile.flush();
logfile.close();
LowPower.deepSleep(1000);
}

// wakeup function
void wakeupProc() {
u8g2.setPowerSave(0);
u8g2.begin();

u8g2.clearBuffer();
u8g2.drawXBMP(0, 0, mouth1_width, mouth1_height, mouth1_bits);
u8g2.sendBuffer();
delay(2000);
u8g2.clearBuffer();

#if defined(FAKERPM)
pinMode(RPMPOWER, INPUT);
digitalWrite(RPMPOWER, LOW);
#else
pinMode(RPMPOWER, OUTPUT);
pinMode(CHTPOWER, OUTPUT);
digitalWrite(RPMPOWER, HIGH);
#endif
pinMode(CHTPOWER, OUTPUT);
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(CHTPOWER, HIGH);
total_runtime = EEPROMReadlong(0);

char filename[17];
strcpy(filename, "logger/HOURS.TXT");
// for (uint8_t i = 0; i < 100; i++) {
// filename[10] = '0' + i / 10;
// filename[11] = '0' + i % 10;
// // create if does not exist, do not open existing, write, sync after
// write if (!SD.exists(filename)) {
// break;
// }
// }
logfile = SD.open(filename, FILE_READ);
if (!logfile) {
#if defined(DEVMODE)
Serial.print("Couldnt open ");
Serial.println(filename);
#endif
error(2);
}

while (logfile.available()) {
unsigned long runtime_temp = logfile.parseInt();
if (runtime_temp > 0) {
total_runtime = runtime_temp;
}
}
#if defined(DEVMODE)
Serial.println(total_runtime);
#endif
logfile.close();

logfile = SD.open(filename, FILE_WRITE);
logfile.seek(EOF);
if (!logfile) {
#if defined(DEVMODE)
Serial.print("Couldnt open for write ");
Serial.println(filename);
#endif
error(3);
}

// total_runtime = EEPROMReadlong(0);
}

void setup() {
Expand All @@ -120,10 +189,18 @@ void setup() {
// initialize serial:
#if defined(DEVMODE)
Serial.begin(115200);
Serial.print("Devmode ON");
while (!Serial) delay(10); // wait for native usb
Serial.println("Devmode ON");
#endif

Wire.setClock(400000);
u8g2.setBusClock(400000);
u8g2.begin();

if (!SD.begin(chipSelect)) {
#if defined(DEVMODE)
Serial.println("SD init failed");
#endif
}
wakeupProc();
}

Expand Down Expand Up @@ -155,6 +232,9 @@ void loop() {
while (Serial.available() > 0) {
// look for the next valid integer in the incoming serial stream:
rev = Serial.parseInt();
#if defined(FAKERPM)
fakerpm_dt = 60000.0 / rev;
#endif
if (Serial.read() == '\n') {
Serial.println(rev);
if (rev < 0) {
Expand All @@ -164,15 +244,29 @@ void loop() {
}
}
}

#if defined(FAKERPM)
if (millis() - fakerpm_tt > fakerpm_dt) {
// pinmode input detaches internal pullup, so transistor in pcb takes pin
// to 0V however, it also detaches the interrupt for some reason
pinMode(RPMPIN, INPUT);
delayMicroseconds(20);
pinMode(RPMPIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(RPMPIN), rpm_isr, FALLING);
fakerpm_tt = millis();
}
#endif

// Serial.println(rpm_filt);
#endif
if (millis() - tt_loop > loopUpdateTime) {
updateRunningTime();
updateTacho();
readCht();
#if !defined(FAKERPM)
readBatteryVoltage();
readCht();
updateMainDisplay();
#endif
tt_loop = millis();
}
} else {
Expand Down Expand Up @@ -279,22 +373,32 @@ void readBatteryVoltage() {
#endif
}

void rpm_isr() { rev++; }
void rpm_isr() {
t1 = micros();
rev++;
}

void updateTacho() {
dt = micros() - oldtime;
oldtime = micros();
if (dt > 0) {
rpm = (rev / dt) * 60000000;
if (rev > 0) {
dt = t1 - t0;
if (dt > 0) {
rpm = (rev / dt) * 60000000;
t0 = t1;
#if defined(FAKERPM)
rev = 0;
#endif
#if !defined(DEVMODE)
rev = 0;
rev = 0;
#endif
}
rpm_filt =
constrain((1 / ww) * (rpm) + (1 - (1 / ww)) * rpm_filt, 0, max_rpm);
}
rpm_filt =
constrain((1 / ww) * (rpm) + (1 - (1 / ww)) * rpm_filt, 0, max_rpm);
#if defined(DEVMODE)
Serial.print("rpm: ");
Serial.println(rpm_filt);
Serial.print("rpm: ");
Serial.print(rpm_filt);
Serial.print(" ");
Serial.println(dt);
}
#endif
}

Expand All @@ -317,6 +421,8 @@ typedef struct barStruct {
} barStruct;

void updateMainDisplay() {
// u8g2.clearBuffer();

barStruct rpmBar;
rpmBar.value = rpm_filt / 1000;
rpmBar.x = 0;
Expand Down Expand Up @@ -535,7 +641,7 @@ void drawBar(
u8g2.drawHLine(pp.x, pp.y + 10, 5);
u8g2.drawHLine(pp.x + 52 - 4, pp.y + 10, 5);

int width = constrain(map(pp.value, pp.min, pp.max, 0, 49), 0, 49);
int width = constrain(map_float(pp.value, pp.min, pp.max, 0, 49), 0, 49);
for (int i = 0; i < width; i++) {
u8g2.drawVLine(pp.x + i + 2, pp.y + 2, 7);
}
Expand All @@ -562,3 +668,8 @@ void drawBar(
// }
// }
}

float map_float(float x, float in_min, float in_max, float out_min,
float out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
46 changes: 46 additions & 0 deletions Arduino code/src/graphics.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#define mouth1_width 128
#define mouth1_height 32
static const unsigned char mouth1_bits[] = {
0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0x07, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x80, 0xFF, 0x3F, 0x00,
0xC0, 0x0F, 0x00, 0xF0, 0x03, 0x00, 0xF8, 0x03, 0x00, 0xFC, 0xFF, 0x00,
0xF0, 0x0F, 0x0E, 0x00, 0x00, 0x07, 0x00, 0xC0, 0x01, 0x00, 0xE0, 0x00,
0x00, 0x38, 0xFC, 0x07, 0xFC, 0x0F, 0x0E, 0x00, 0x00, 0x07, 0x00, 0xC0,
0x01, 0x00, 0xE0, 0x00, 0x00, 0x38, 0xF0, 0x1F, 0xFC, 0x01, 0x0E, 0x00,
0x00, 0x07, 0x00, 0xC0, 0x01, 0x00, 0xE0, 0x00, 0x00, 0x38, 0xC0, 0x3F,
0x7F, 0x00, 0x0E, 0x00, 0x00, 0x07, 0x00, 0xC0, 0x01, 0x00, 0xE0, 0x00,
0x00, 0x38, 0x00, 0x7F, 0x7F, 0x00, 0x0E, 0x00, 0x00, 0x07, 0x00, 0xC0,
0x01, 0x00, 0xE0, 0x00, 0x00, 0x38, 0x00, 0xFE, 0x3F, 0x00, 0x0E, 0x00,
0x00, 0x07, 0x00, 0xC0, 0x01, 0x00, 0xE0, 0x00, 0x00, 0x38, 0x00, 0xFE,
0x3F, 0x00, 0x0E, 0x00, 0x00, 0x07, 0x00, 0xE0, 0xFF, 0x00, 0xE0, 0x00,
0x00, 0x38, 0x00, 0xFC, 0x3F, 0x00, 0x0E, 0x00, 0x00, 0x07, 0xF0, 0xFF,
0xFF, 0x3F, 0xE0, 0x00, 0x00, 0x3C, 0x00, 0xFC, 0x3F, 0x00, 0x0E, 0x00,
0x00, 0x07, 0xFE, 0xFF, 0x01, 0xFF, 0xE3, 0x00, 0x00, 0x1C, 0x00, 0xFC,
0x3F, 0x00, 0x0E, 0x00, 0x00, 0xFF, 0x7F, 0xC0, 0x01, 0xC0, 0xFF, 0x01,
0x00, 0x1C, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xC0,
0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0x07, 0x00, 0xC0, 0x01, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x3F, 0x00, 0x1E, 0x00, 0x00, 0x07, 0x00, 0xC0, 0x01, 0x00, 0xE0, 0x00,
0x00, 0x1C, 0x00, 0xFC, 0x3F, 0x00, 0x1C, 0x00, 0x00, 0x07, 0x00, 0xC0,
0x01, 0x00, 0xE0, 0x00, 0x00, 0x1C, 0x00, 0xFC, 0x3F, 0x00, 0x1C, 0x00,
0x00, 0x07, 0x00, 0xC0, 0x01, 0x00, 0xE0, 0x00, 0x00, 0x1C, 0x00, 0xFC,
0xFF, 0x0F, 0x1C, 0x00, 0x00, 0x07, 0x00, 0xC0, 0x01, 0x00, 0xE0, 0x00,
0x00, 0x1C, 0x00, 0xFC, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x07, 0x00, 0xC0,
0x01, 0x00, 0xE0, 0x00, 0x00, 0x1C, 0x00, 0xFC, 0x3F, 0xFC, 0xFF, 0x7F,
0x00, 0x07, 0x00, 0xC0, 0x01, 0x00, 0xE0, 0x00, 0x00, 0xFC, 0xFF, 0xFF,
0x3F, 0x00, 0xFC, 0xFF, 0x3F, 0x07, 0x00, 0xC0, 0x01, 0x00, 0xE0, 0xC0,
0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x38, 0xFE, 0xFF, 0xFF, 0x01, 0xC0,
0x01, 0xFC, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0xFC, 0x7F, 0x00, 0x38, 0x00,
0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x1C, 0x00, 0x7E,
0x7E, 0x00, 0x38, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0x07, 0x70, 0x00,
0x00, 0x1C, 0x00, 0x7F, 0xFE, 0x00, 0x38, 0x00, 0x00, 0x07, 0x00, 0xC0,
0x01, 0x00, 0x70, 0x00, 0x00, 0x1C, 0x00, 0x7F, 0xFC, 0x01, 0x38, 0x00,
0x00, 0x07, 0x00, 0xC0, 0x01, 0x00, 0x70, 0x00, 0x00, 0x1C, 0xC0, 0x3F,
0xF8, 0x07, 0x38, 0x00, 0x00, 0x07, 0x00, 0xC0, 0x01, 0x00, 0x70, 0x00,
0x00, 0x1C, 0xE0, 0x1F, 0xF0, 0x1F, 0x38, 0x00, 0x00, 0x07, 0x00, 0xC0,
0x01, 0x00, 0x70, 0x00, 0x00, 0x1C, 0xFC, 0x07, 0xC0, 0x7F, 0x38, 0x00,
0x00, 0x07, 0x00, 0xC0, 0x01, 0x00, 0x70, 0x00, 0x00, 0x1C, 0xFC, 0x01,
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x01, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, };

0 comments on commit bf085c6

Please sign in to comment.