Skip to content
Snippets Groups Projects
Commit 047fe715 authored by Bram Veenboer's avatar Bram Veenboer
Browse files

Update Arduino directory

parent aaad2c75
Branches
Tags
No related merge requests found
#NO_CORE= 1
#MCU= m328p
#F_CPU= 16000000
#VARIANT= standard
TARGET= PowerSensor
BOARD_TAG= uno
#ARDUINO_PORT= /dev/ttyACM0
ARDUINO_PORT= /dev/ttyUSB0
BOARD_TAG= leonardo
ARDUINO_PORT= /dev/ttyACM0
include /usr/share/arduino/Arduino.mk
......@@ -32,79 +32,75 @@ struct EEPROM
struct Sensor {
double volt;
double type;
int16_t nullLevels;
double nullLevel;
} sensors[MAX_SENSORS];
} eeprom __attribute__((section(".eeprom")));
int64_t accumulated_values[MAX_SENSORS];
int16_t levels[MAX_SENSORS];
long previous_time;
double weights[MAX_SENSORS];
int16_t nullLevels[MAX_SENSORS];
bool inUse[MAX_SENSORS];
struct Sensor
{
bool inUse;
uint16_t count;
int32_t total;
double weight;
double nullLevel;
double power() const { return weight * total / count - nullLevel; }
int64_t total_accumulated_value()
{
int64_t sum = 0;
} sensors[MAX_SENSORS];
for (uint8_t sensor = 0; sensor < MAX_SENSORS; sensor ++)
if (inUse[sensor])
sum += weights[sensor] * accumulated_values[sensor];
return sum;
}
bool streamValues = false;
inline uint8_t next_sensor(uint8_t current_sensor)
inline uint8_t nextSensor(uint8_t currentSensor)
{
do
if (++ current_sensor == MAX_SENSORS)
current_sensor = 0;
while (!inUse[current_sensor]);
if (++ currentSensor == MAX_SENSORS)
currentSensor = 0;
while (!sensors[currentSensor].inUse);
return currentSensor;
}
return current_sensor;
inline void setADMUX(uint8_t sensor)
{
#if defined __AVR_ATmega32U4__
ADMUX = _BV(REFS0) | ((sensor <= 2 ? 6 : 4) - sensor);
#else
ADMUX = _BV(REFS0) | (sensor + 1); // ADC0 reads the LCD buttons; skip it
#endif
}
ISR(ADC_vect)
{
static uint8_t current_sensor = 0;
static uint8_t currentSensor = 0;
uint8_t low = ADCL, high = ADCH; // read in this order
levels[current_sensor] = (high << 8) | low;
// start next ADC ASAP.
uint8_t previous_sensor = current_sensor;
current_sensor = next_sensor(current_sensor);
uint8_t previousSensor = currentSensor;
currentSensor = nextSensor(currentSensor);
ADMUX = _BV(REFS0) | (current_sensor + 1); // ADC0 reads the LCD buttons; skip it
setADMUX(currentSensor);
ADCSRA |= _BV(ADSC); // start ADC conversion
// handle measured value
if (current_sensor <= previous_sensor) {
// we had one round of all sensors. now handle them in one go
long measured_time = micros();
long time_difference = measured_time - previous_time;
previous_time = measured_time;
int16_t level = (high << 8) | low;
sensors[previousSensor].total += level - 512;
sensors[previousSensor].count ++;
for (uint8_t sensor = 0; sensor < MAX_SENSORS; sensor ++)
// compiler will generate 16x16 bit multiply producing 32-bit result
accumulated_values[sensor] += (long) (int) time_difference * (levels[sensor] - nullLevels[sensor]);
}
}
if (streamValues) {
Serial.write((previousSensor << 5) | (level >> 5));
Serial.write(0xE0 | (level & 0x1F));
#if defined __AVR_ATmega32U4__
Serial.flush();
#endif
void readState()
{
noInterrupts();
int32_t total = total_accumulated_value() >> 16;
Serial.write((const uint8_t *) &total, sizeof total);
Serial.write((const uint8_t *) &previous_time, sizeof previous_time);
interrupts();
//for (int i = 2; i < 16; i ++)
//Serial.write(0);
}
}
......@@ -114,9 +110,9 @@ void configureFromEEPROM()
eeprom_read_block(&copy, &eeprom, sizeof copy);
for (unsigned i = 0; i < MAX_SENSORS; i ++) {
inUse[i] = copy.sensors[i].volt != 0;
weights[i] = inUse[i] ? copy.sensors[i].volt * 2.5 / copy.sensors[i].type : 0;
nullLevels[i] = copy.sensors[i].nullLevels;
sensors[i].inUse = copy.sensors[i].volt != 0;
sensors[i].weight = sensors[i].inUse ? (2.5 / 512) * (copy.sensors[i].volt / copy.sensors[i].type) : 0;
sensors[i].nullLevel = copy.sensors[i].nullLevel;
}
}
......@@ -131,7 +127,10 @@ void readConfig()
void writeConfig()
{
#if !defined __AVR_ATmega32U4__
Serial.begin(115200); // serial comm from host to Arduino seems less reliable --> reduce baud rate
#endif
EEPROM copy;
for (unsigned i = 0; i < sizeof copy; i ++) {
......@@ -141,31 +140,32 @@ void writeConfig()
((uint8_t *) &copy)[i] = Serial.read();
}
Serial.begin(2000000); // probably only neecssary on Leonardo, that does not automatically reset after creating a new connection
#if !defined __AVR_ATmega32U4__
Serial.begin(2000000);
#endif
eeprom_update_block(&copy, &eeprom, sizeof copy);
configureFromEEPROM();
}
void readLevels()
{
Serial.write((const uint8_t *) levels, sizeof levels);
}
void serialEventRun()
{
switch (Serial.read()) {
case 'l': readLevels();
case 'r': readConfig();
break;
case 'r': readConfig();
case 'w': writeConfig();
break;
case 's': readState();
case 'S': streamValues = true;
break;
case 'w': writeConfig();
case 'T': streamValues = false;
break;
case 'X': streamValues = false;
Serial.write((const uint8_t []) { 0xFF, 0xE0 }, 2);
break;
}
}
......@@ -182,7 +182,7 @@ void setup()
Serial.begin(2000000);
ADMUX = _BV(REFS0) + 1;
setADMUX(0);
ADCSRA |= _BV(ADIE); // enable ADC interrupts
ADCSRA |= _BV(ADSC); // start ADC conversion
}
......@@ -190,51 +190,52 @@ void setup()
void loop()
{
static unsigned long previous_print_time;
static int64_t previous_value_of_next_sensor, previous_value_total;
static uint8_t count, current_sensor = next_sensor(MAX_SENSORS - 1), current_line;
noInterrupts();
static unsigned long previousPrintTime;
static uint8_t count, currentSensor = nextSensor(MAX_SENSORS - 1), currentLine;
unsigned long current_time = micros(), time_difference = current_time - previous_print_time;
uint16_t currentTime = millis(), timeDifference = currentTime - previousPrintTime;
if (time_difference > 333333) {
if (timeDifference > 333) {
double power;
if (current_line == 0) {
if (currentLine == 0) {
// print top line; rotate among the used sensors
int64_t total = weights[current_sensor] * accumulated_values[current_sensor];
if ((++ count & 7) == 0)
current_sensor = next_sensor(current_sensor);
power = (double) (total - previous_value_of_next_sensor) / (512 * time_difference);
previous_value_of_next_sensor = weights[current_sensor] * accumulated_values[current_sensor];
noInterrupts();
power = sensors[currentSensor].power();
interrupts();
if ((++ count & 7) == 0)
currentSensor = nextSensor(currentSensor);
if ((count & 7) == 1) {
lcd.setCursor(7, 0);
lcd.print((char) ('0' + current_sensor));
lcd.print((char) ('0' + currentSensor));
}
} else { // current_line == 1
} else { // currentLine == 1
// print bottom line; the sum of all sensors
int64_t total = total_accumulated_value();
power = 0;
noInterrupts();
for (uint8_t sensor = 0; sensor < MAX_SENSORS; sensor ++) {
if (sensors[sensor].inUse) {
power += sensors[sensor].power();
sensors[sensor].total = 0;
sensors[sensor].count = 0;
}
}
interrupts();
power = (double) (total - previous_value_total) / (512 * time_difference);
previous_value_total = total;
previous_print_time = current_time;
previousPrintTime = currentTime;
}
char buffer[16];
dtostrf(power, 6, 1, buffer);
lcd.setCursor(9, current_line);
lcd.setCursor(9, currentLine);
lcd.print(buffer);
current_line ^= 1;
currentLine ^= 1;
}
interrupts();
}
#if !defined SEMAPHORE_H
#define SEMAPHORE_H
#include <condition_variable>
#include <mutex>
namespace PowerSensor {
class Semaphore
{
public:
Semaphore(unsigned initialLevel = 0)
:
level(initialLevel)
{
}
void up(unsigned count = 1)
{
std::unique_lock<std::mutex> lock(mutex);
level += count;
if (count == 1)
cv.notify_one();
else
cv.notify_all();
}
void down(unsigned count = 1)
{
std::unique_lock<std::mutex> lock(mutex);
cv.wait(lock, [this, count] { return level >= count; });
level -= count;
}
private:
std::mutex mutex;
std::condition_variable cv;
unsigned level;
};
}
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment