From 3bcfb8ccce9d1e07c1e3426a52cbf85e14dae936 Mon Sep 17 00:00:00 2001 From: Bram Veenboer <bram.veenboer@gmail.com> Date: Mon, 31 Oct 2016 14:14:21 +0100 Subject: [PATCH] Add src --- src/Arduino/Makefile | 9 ++ src/Arduino/PowerSensor.ino | 240 ++++++++++++++++++++++++++++++++++++ src/Makefile | 30 +++++ src/PowerSensor.cc | 239 +++++++++++++++++++++++++++++++++++ src/PowerSensor.h | 70 +++++++++++ src/psconfig | 195 +++++++++++++++++++++++++++++ src/testPowerSensor.cc | 59 +++++++++ 7 files changed, 842 insertions(+) create mode 100644 src/Arduino/Makefile create mode 100644 src/Arduino/PowerSensor.ino create mode 100644 src/Makefile create mode 100644 src/PowerSensor.cc create mode 100644 src/PowerSensor.h create mode 100755 src/psconfig create mode 100644 src/testPowerSensor.cc diff --git a/src/Arduino/Makefile b/src/Arduino/Makefile new file mode 100644 index 0000000..a1f4a20 --- /dev/null +++ b/src/Arduino/Makefile @@ -0,0 +1,9 @@ +#NO_CORE= 1 +#MCU= m328p +#F_CPU= 16000000 +#VARIANT= standard +TARGET= PowerSensor +BOARD_TAG= uno +#ARDUINO_PORT= /dev/ttyACM0 +ARDUINO_PORT= /dev/ttyUSB0 +include /usr/share/arduino/Arduino.mk diff --git a/src/Arduino/PowerSensor.ino b/src/Arduino/PowerSensor.ino new file mode 100644 index 0000000..b0385ee --- /dev/null +++ b/src/Arduino/PowerSensor.ino @@ -0,0 +1,240 @@ +// Copyright (C) 2016 +// ASTRON (Netherlands Institute for Radio Astronomy) / John W. Romein +// P.O. Box 2, 7990 AA Dwingeloo, the Netherlands + +// This file is part of PowerSensor. + +// PowerSensor is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// PowerSensor is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with PowerSensor. If not, see <http://www.gnu.org/licenses/>. + + +#include <avr/eeprom.h> +#include <Wire.h> +#include <LiquidCrystal.h> + +LiquidCrystal lcd(8, 9, 4, 5, 6, 7); + + +#define MAX_SENSORS 5 + +struct EEPROM +{ + struct Sensor { + double volt; + double type; + int16_t nullLevels; + } 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]; + + +int64_t total_accumulated_value() +{ + int64_t sum = 0; + + for (uint8_t sensor = 0; sensor < MAX_SENSORS; sensor ++) + if (inUse[sensor]) + sum += weights[sensor] * accumulated_values[sensor]; + + return sum; +} + + +inline uint8_t next_sensor(uint8_t current_sensor) +{ + do + if (++ current_sensor == MAX_SENSORS) + current_sensor = 0; + while (!inUse[current_sensor]); + + return current_sensor; +} + + +ISR(ADC_vect) +{ + static uint8_t current_sensor = 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); + + ADMUX = _BV(REFS0) | (current_sensor + 1); // ADC0 reads the LCD buttons; skip it + 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; + + 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]); + } +} + + +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(); +} + + +void configureFromEEPROM() +{ + EEPROM copy; + eeprom_read_block(©, &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; + } +} + + +void readConfig() +{ + EEPROM copy; + eeprom_read_block(©, &eeprom, sizeof copy); + Serial.write((const uint8_t *) ©, sizeof copy); +} + + +void writeConfig() +{ + Serial.begin(115200); // serial comm from host to Arduino seems less reliable --> reduce baud rate + EEPROM copy; + + for (unsigned i = 0; i < sizeof copy; i ++) { + while (Serial.available() == 0) + ; + + ((uint8_t *) ©)[i] = Serial.read(); + } + + Serial.begin(2000000); // probably only neecssary on Leonardo, that does not automatically reset after creating a new connection + eeprom_update_block(©, &eeprom, sizeof copy); + configureFromEEPROM(); +} + + +void readLevels() +{ + Serial.write((const uint8_t *) levels, sizeof levels); +} + + +void serialEventRun() +{ + switch (Serial.read()) { + case 'l': readLevels(); + break; + + case 'r': readConfig(); + break; + + case 's': readState(); + break; + + case 'w': writeConfig(); + break; + } +} + + +void setup() +{ + configureFromEEPROM(); + + lcd.begin(16, 2); + lcd.print("Sensor : W"); + lcd.setCursor(0, 1); + lcd.print("Total: W"); + + Serial.begin(2000000); + + ADMUX = _BV(REFS0) + 1; + ADCSRA |= _BV(ADIE); // enable ADC interrupts + ADCSRA |= _BV(ADSC); // start ADC conversion +} + + +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(); + + unsigned long current_time = micros(), time_difference = current_time - previous_print_time; + + if (time_difference > 333333) { + double power; + + if (current_line == 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]; + + interrupts(); + + if ((count & 7) == 1) { + lcd.setCursor(7, 0); + lcd.print((char) ('0' + current_sensor)); + } + } else { // current_line == 1 + // print bottom line; the sum of all sensors + int64_t total = total_accumulated_value(); + + interrupts(); + + power = (double) (total - previous_value_total) / (512 * time_difference); + previous_value_total = total; + previous_print_time = current_time; + } + + char buffer[16]; + dtostrf(power, 6, 1, buffer); + lcd.setCursor(9, current_line); + lcd.print(buffer); + + current_line ^= 1; + } + + interrupts(); +} diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..4ac9732 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,30 @@ +ARCH=$(shell arch) +CXX= g++ +CXXFLAGS= -O2 -g -pthread -fopenmp + +obj/$(ARCH)/%.o: %.cc + $(CXX) -c $(CXXFLAGS) $< -o $@ + +all:: lib/$(ARCH)/libPowerSensor.a bin/$(ARCH)/testPowerSensor arduino + +lib/$(ARCH)/libPowerSensor.a: obj/$(ARCH)/PowerSensor.o lib/$(ARCH) + $(AR) cr $@ $< + +bin/$(ARCH)/testPowerSensor: obj/$(ARCH)/testPowerSensor.o lib/$(ARCH)/libPowerSensor.a bin/$(ARCH) + $(CXX) $(CXXFLAGS) obj/$(ARCH)/testPowerSensor.o -Llib/$(ARCH) -lPowerSensor -o $@ + +obj/$(ARCH)/testPowerSensor.o: testPowerSensor.cc PowerSensor.h obj/$(ARCH) + +obj/$(ARCH)/PowerSensor.o: PowerSensor.cc PowerSensor.h obj/$(ARCH) + +obj/$(ARCH) lib/$(ARCH) bin/$(ARCH): + mkdir -p $@ + +arduino:: + +make -C Arduino + +upload:: all + +make -C Arduino upload + +clean:: + make -C Arduino clean diff --git a/src/PowerSensor.cc b/src/PowerSensor.cc new file mode 100644 index 0000000..c9bedad --- /dev/null +++ b/src/PowerSensor.cc @@ -0,0 +1,239 @@ +// Copyright (C) 2016 +// ASTRON (Netherlands Institute for Radio Astronomy) / John W. Romein +// P.O. Box 2, 7990 AA Dwingeloo, the Netherlands + +// This file is part of PowerSensor. + +// PowerSensor is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// PowerSensor is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with PowerSensor. If not, see <http://www.gnu.org/licenses/>. + + +#include "PowerSensor.h" + +#include <cstdio> +#include <cstdlib> +#include <iostream> + +#include <errno.h> +#include <fcntl.h> +#include <omp.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <termios.h> +#include <unistd.h> + + + +PowerSensor::PowerSensor(const char *device, const char *dumpFileName) +: + dumpFile(dumpFileName == 0 ? 0 : new std::ofstream(dumpFileName)), + stop(false) +{ + lastState.microSeconds = 0; + + if ((fd = open(device, O_RDWR)) < 0) { + perror("open device"); + exit(1); + } + + + //Configure port for 8N1 transmission + struct termios options; + + tcgetattr(fd, &options); //Gets the current options for the port + cfsetispeed(&options, B2000000); //Sets the Input Baud Rate + cfsetospeed(&options, B2000000); //Sets the Output Baud Rate + + options.c_cflag = (options.c_cflag & ~CSIZE) | CS8; + options.c_iflag = IGNBRK; + options.c_lflag = 0; + options.c_oflag = 0; + options.c_cflag |= CLOCAL | CREAD; + options.c_cc[VMIN] = sizeof(State::MC_State); + options.c_cc[VTIME] = 0; + options.c_iflag &= ~(IXON | IXOFF | IXANY); + options.c_cflag &= ~(PARENB | PARODD); + + /* commit the options */ + tcsetattr(fd, TCSANOW, &options); + + /* Wait for the Arduino to reset */ + sleep(2); + /* Flush anything already in the serial buffer */ + tcflush(fd, TCIFLUSH); + + if ((errno = pthread_mutex_init(&mutex, 0)) != 0) { + perror("pthread_mutex_init"); + exit(1); + } + + doMeasurement(); // initialise + + if ((errno = pthread_create(&thread, 0, &PowerSensor::IOthread, this)) != 0) { + perror("pthread_create"); + exit(1); + } +} + + +PowerSensor::~PowerSensor() +{ + stop = true; + + if ((errno = pthread_join(thread, 0)) != 0) + perror("pthread_join"); + + if ((errno = pthread_mutex_destroy(&mutex)) != 0) + perror("pthread_mutex_destroy"); + + if (close(fd)) + perror("close device"); + + if (dumpFile != 0) + delete dumpFile; +} + + +void PowerSensor::lock() +{ + if ((errno = pthread_mutex_lock(&mutex)) != 0) { + perror("pthread_mutex_lock"); + exit(1); + } +} + + +void PowerSensor::unlock() +{ + if ((errno = pthread_mutex_unlock(&mutex)) != 0) { + perror("pthread_mutex_unlock"); + exit(1); + } +} + + +void *PowerSensor::IOthread(void *arg) +{ + return static_cast<PowerSensor *>(arg)->IOthread(); +} + + +void *PowerSensor::IOthread() +{ + while (!stop) + doMeasurement(); + + return 0; +} + + +void PowerSensor::doMeasurement() +{ + State::MC_State currentState; + + ssize_t retval, bytesRead = 0; + + if (write(fd, "s", 1) != 1) { + perror("write device"); + exit(1); + } + + do { + if ((retval = ::read(fd, (char *) ¤tState.consumedEnergy + bytesRead, sizeof(State::MC_State) - bytesRead)) < 0) { + perror("read device"); + exit(1); + } + } while ((bytesRead += retval) < sizeof(State::MC_State)); + + lock(); + + if (lastState.microSeconds != currentState.microSeconds) { + previousState = lastState; + lastState = currentState; + + if (dumpFile != 0) + *dumpFile << "S " << currentState.microSeconds / 1e6 << ' ' << (currentState.consumedEnergy - previousState.consumedEnergy) * (65536.0 / 512) / (currentState.microSeconds - previousState.microSeconds) << std::endl; + } + +#if 0 + static double lastTime; + static unsigned count; + ++ count; + + if (lastTime + 1 < omp_get_wtime()) { +#pragma omp critical (cout) + std::cout << "nr times read = " << count << std::endl; + lastTime = omp_get_wtime(); + count = 0; + } +#endif + + unlock(); +} + + +void PowerSensor::mark(const State &state, const char *name, unsigned tag) +{ + if (dumpFile != 0) { + lock(); + *dumpFile << "M " << state.lastState.microSeconds * 1e-6 << ' ' << tag << " \"" << (name == 0 ? "" : name) << '"' << std::endl; + unlock(); + } +} + + +void PowerSensor::mark(const State &startState, const State &stopState, const char *name, unsigned tag) +{ + if (dumpFile != 0) { + lock(); + *dumpFile << "M " << startState.lastState.microSeconds * 1e-6 << ' ' << stopState.lastState.microSeconds * 1e-6 << ' ' << tag << " \"" << (name == 0 ? "" : name) << '"' << std::endl; + unlock(); + } +} + + +PowerSensor::State PowerSensor::read() +{ + State state; + + lock(); + state.previousState = previousState; + state.lastState = lastState; + state.timeAtRead = omp_get_wtime(); + unlock(); + + return state; +} + + +double PowerSensor::Joules(const State &firstState, const State &secondState) +{ + return Watt(firstState, secondState) * seconds(firstState, secondState); +} + + +double PowerSensor::seconds(const State &firstState, const State &secondState) +{ + return secondState.timeAtRead - firstState.timeAtRead; +} + + +double PowerSensor::Watt(const State &firstState, const State &secondState) +{ + uint32_t microSeconds = secondState.lastState.microSeconds - firstState.lastState.microSeconds; + + if (microSeconds != 0) + return (secondState.lastState.consumedEnergy - firstState.lastState.consumedEnergy) * (65536.0 / 512) / microSeconds; + else // very short time + return (secondState.lastState.consumedEnergy - secondState.previousState.consumedEnergy) * (65536.0 / 512) / (secondState.lastState.microSeconds - secondState.previousState.microSeconds); +} diff --git a/src/PowerSensor.h b/src/PowerSensor.h new file mode 100644 index 0000000..783d8b0 --- /dev/null +++ b/src/PowerSensor.h @@ -0,0 +1,70 @@ +// Copyright (C) 2016 +// ASTRON (Netherlands Institute for Radio Astronomy) / John W. Romein +// P.O. Box 2, 7990 AA Dwingeloo, the Netherlands + +// This file is part of PowerSensor. + +// PowerSensor is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// PowerSensor is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with PowerSensor. If not, see <http://www.gnu.org/licenses/>. + + +#if !defined POWER_SENSOR_H +#define POWER_SENSOR_H + +#include <inttypes.h> +#include <pthread.h> + +#include <fstream> + + +class PowerSensor +{ + public: + struct State + { + struct MC_State + { + int32_t consumedEnergy; + uint32_t microSeconds; + } previousState, lastState; + + double timeAtRead; + }; + + PowerSensor(const char *device = "/dev/ttyACM0", const char *dumpFileName = 0); + ~PowerSensor(); + + State read(); + void mark(const State &, const char *name = 0, unsigned tag = 0); + void mark(const State &start, const State &stop, const char *name = 0, unsigned tag = 0); + + static double Joules(const State &firstState, const State &secondState); + static double seconds(const State &firstState, const State &secondState); + static double Watt(const State &firstState, const State &secondState); + + private: + int fd; + std::ofstream *dumpFile; + pthread_t thread; + pthread_mutex_t mutex; + volatile bool stop; + State::MC_State previousState, lastState; + + void lock(), unlock(); + + static void *IOthread(void *); + void *IOthread(); + void doMeasurement(); +}; + +#endif diff --git a/src/psconfig b/src/psconfig new file mode 100755 index 0000000..2b4356a --- /dev/null +++ b/src/psconfig @@ -0,0 +1,195 @@ +#!/usr/bin/python + +# Copyright (C) 2016 +# ASTRON (Netherlands Institute for Radio Astronomy) / John W. Romein +# P.O. Box 2, 7990 AA Dwingeloo, the Netherlands + +# This file is part of PowerSensor. + +# PowerSensor is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# PowerSensor is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with PowerSensor. If not, see <http://www.gnu.org/licenses/>. + + +import getopt, serial, sys, time, struct + +maxSensors = 5 + + +def approximates(a, b): + return a / b > .999999 and a / b < 1.000001 + +class Sensor: + def readEEPROM(self, ser): + self.volt, self.voltPerAmpere, self.nullLevel = struct.unpack("<ffh", ser.read(10)) + + def writeEEPROM(self, ser): + ser.write(struct.pack("<ffh", self.volt, self.voltPerAmpere, self.nullLevel)) + + def readLevel(self, ser): + self.level = struct.unpack("<h", ser.read(2))[0] + + +class EEPROM: + def __init__(self, device = "/dev/ttyUSB0"): + self.ser = None + + try: + self.ser = serial.Serial(device, 2000000); + except serial.SerialException: + print "Could not open", device + sys.exit(1) + + time.sleep(2) # wait until device reset complete + + # read EEPROM sensor configuration + self.sensors = [] + self.ser.write('r') + + for i in range(maxSensors): + self.sensors.append(Sensor()) + self.sensors[i].readEEPROM(self.ser) + + # read current sensor levels + self.ser.write('l') + + for sensor in self.sensors: + sensor.readLevel(self.ser) + + self.currentSensor = self.sensors[0] + + + def __del__(self): + if self.ser != None: # may be None if constructor threw exception + self.ser.write('w') + self.ser.flush() # serial comm from host to Arduino seems less reliable --> reduce baud rate + time.sleep(.2) + self.ser.baudrate = 115200 + + for sensor in self.sensors: + sensor.writeEEPROM(self.ser) + + self.ser.close() + + + def setSensor(self, arg): + sensorNumber = int(arg) + + if sensorNumber < 0 or sensorNumber >= maxSensors: + print >> sys.stderr, 'illegal sensor number' + sys.exit(1) + + self.currentSensor = self.sensors[sensorNumber] + + + def setNullLevel(self, arg): + if arg == "auto": + arg = self.currentSensor.level - 512 + + if int(arg) < -512 or int(arg) >= 512: + print >> sys.stderr, 'illegal nullLevel value' + sys.exit(1) + + self.currentSensor.nullLevel = int(arg) + 512 + + + def setVolt(self, arg): + self.currentSensor.volt = float(arg) + + + def setType(self, arg): + if arg in ("acs712-5", "ACS712-5"): + voltPerAmpere = 0.185 + elif arg in ("acs712-20", "ACS712-20"): + voltPerAmpere = 0.1 + elif arg in ("acs712-30", "ACS712-30"): + voltPerAmpere = 0.66 + else: + voltPerAmpere = float(arg) + + self.currentSensor.voltPerAmpere = voltPerAmpere + + + def doPrint(self): + totalWatt = 0.0 + + for i in range(len(self.sensors)): + sensor = self.sensors[i] + + if approximates(sensor.voltPerAmpere, 0.185): + sensorType = "type = ACS712-5" + elif approximates(sensor.voltPerAmpere, 0.1): + sensorType = "type = ACS712-20" + elif approximates(sensor.voltPerAmpere, 0.66): + sensorType = "type = ACS712-30" + else: + sensorType = "voltPerAmpere = " + str(sensor.voltPerAmpere) + + if sensor.volt == 0: + print "sensor %u: off" % i + else: + watt = sensor.volt * 2.5 / sensor.voltPerAmpere * (sensor.level - sensor.nullLevel) / 512 + totalWatt += watt + print "sensor %u: volt = %f, %s, nullLevel = %d, level = %d, Watt = %f" % (i, sensor.volt, sensorType, sensor.nullLevel - 512, sensor.level - 512, watt) + + print "total Watt = %f" % totalWatt + + +def printHelp(): + print "Usage: [-d device] [-s sensor_nr] [-v volatage] [-t sensor_type] [-n null_level] [-s next_sensor_nr] [-o] ... [-p]" + print + print "the order in which the arguments appear is important" + print "-h (--help): print this help message" + print "-d dev (--device=dev): use this device (default: /dev/ttyUSB0)" + print "-s sensor_nr (--sensor=sensor_nr): from now on, configuration parameters apply to this sennsor number" + print "-v volt (--voltage=volt: voltage of the rail being measured" + print "-t sensor_type (--type=sensor_type): use this sensor type (ACS712-5, ACS712-20, ACS712-30, or a number indicating the volt/ampere ratio of the sensor" + print "-n null_level (--nulllevel=null_level): null level to be used for calibration. If no current is flowing, use \"-n auto\"" + print "-o (--off): do not use this sensor number" + print "-p (--print): print configuration parameterss and the currently measured sensor values" + + +def getopts(argv): + eeprom = None + + try: + opts, argv = getopt.getopt(argv, "d:hn:ops:t:v:", ["device=", "help", "nulllevel=", "off", "print", "sensor=", "type=", "voltage="]) + except getopt.GetoptError: + printHelp() + sys.exit(1) + + for opt, arg in opts: + if opt in ("-h", "--help"): + printHelp() + sys.exit() + + if opt in ("-d", "--device"): + del eeprom + eeprom = EEPROM(arg) + elif eeprom == None: + eeprom = EEPROM() + + if opt in ("-n", "--nullLevel"): + eeprom.setNullLevel(arg) + elif opt in ("-o", "--off"): + eeprom.setVolt(0.0) + elif opt in ("-p", "--print"): + eeprom.doPrint() + elif opt in ("-s", "--sensor"): + eeprom.setSensor(arg) + elif opt in ("-t", "--type"): + eeprom.setType(arg) + elif opt in ("-v", "--volt"): + eeprom.setVolt(arg) + +if __name__ == "__main__": + getopts(sys.argv[1:]) diff --git a/src/testPowerSensor.cc b/src/testPowerSensor.cc new file mode 100644 index 0000000..a992c4c --- /dev/null +++ b/src/testPowerSensor.cc @@ -0,0 +1,59 @@ +// Copyright (C) 2016 +// ASTRON (Netherlands Institute for Radio Astronomy) / John W. Romein +// P.O. Box 2, 7990 AA Dwingeloo, the Netherlands + +// This file is part of PowerSensor. + +// PowerSensor is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// PowerSensor is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with PowerSensor. If not, see <http://www.gnu.org/licenses/>. + + +#include <iostream> +#include <iomanip> +#include "PowerSensor.h" + +#include <cstdlib> +#include <iostream> + +#include <inttypes.h> +#include <unistd.h> + +#define MAX_MICRO_SECONDS 4000000 + + +int main(int argc, char **argv) +{ + if (argc > 2) { + std::cerr << "usage: " << argv[0] << " [device]" << std::endl; + exit(1); + } + + const char *device = argc == 2 ? argv[1] : "/dev/ttyUSB0"; + PowerSensor powerSensor(device, "/tmp/sensor_values"); + + PowerSensor::State states[2]; + states[0] = powerSensor.read(); + + for (uint32_t micros = 100, i = 1; micros <= MAX_MICRO_SECONDS; micros *= 2, i ^= 1) { + usleep(micros); + states[i] = powerSensor.read(); + + std::cout << "exp. time: " << micros * 1e-6 << " s, " + "measured: " << PowerSensor::seconds(states[i ^ 1], states[i]) << " s, " << + PowerSensor::Joules(states[i ^ 1], states[i]) << " J, " << + PowerSensor::Watt(states[i ^ 1], states[i]) << " W" << + std::endl; + } + + return 0; +} -- GitLab