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

Update Arduino directory

parent aaad2c75
No related branches found
No related tags found
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