diff --git a/psconfig.cc b/psconfig.cc new file mode 100644 index 0000000000000000000000000000000000000000..e087d381b5d20a34c265b86c9b4b6b0814c26234 --- /dev/null +++ b/psconfig.cc @@ -0,0 +1,149 @@ +#include "PowerSensor.h" + +#include <unistd.h> + +#include <cstring> +#include <iostream> +#include <memory> + + +std::unique_ptr<PowerSensor::PowerSensor> powerSensor; +int sensor = 0; + + +float convertType(const char *arg) +{ + if (strcmp(arg, "ACS712-5") == 0 || strcmp(arg, "acs712-5") == 0) + return 0.185; + else if (strcmp(arg, "ACS712-20") == 0 || strcmp(arg, "acs712-20") == 0) + return 0.1; + else if (strcmp(arg, "ACS712-30") == 0 || strcmp(arg, "acs712-30") == 0) + return 0.66; + else + return atof(arg); +} + + +PowerSensor::PowerSensor *checkPowerSensor() +{ + if (powerSensor.get() == nullptr) + powerSensor = std::unique_ptr<PowerSensor::PowerSensor>(new PowerSensor::PowerSensor("/dev/ttyACM0")); + + return powerSensor.get(); +} + + +void measureSensors(PowerSensor::State &startState, PowerSensor::State &stopState) +{ + startState = powerSensor->read(); + sleep(2); + stopState = powerSensor->read(); +} + + +void autoCalibrate() +{ + if (powerSensor->inUse(sensor)) { + PowerSensor::State startState, stopState; + + powerSensor->setNullLevel(sensor, 0); + measureSensors(startState, stopState); + powerSensor->setNullLevel(sensor, PowerSensor::Watt(startState, stopState, sensor)); + } +} + + +bool approximates(float a, float b) +{ + return a / b > .999999 && a / b < 1.000001; +} + + +std::string type(unsigned sensor) +{ + float voltPerAmpere = powerSensor->getType(sensor); + + if (approximates(voltPerAmpere, .185)) + return "ACS712-5"; + else if (approximates(voltPerAmpere, .1)) + return "ACS712-20"; + else if (approximates(voltPerAmpere, .66)) + return "ACS712-30"; + else + return std::to_string(voltPerAmpere) + " V/A"; +} + + +void print() +{ + PowerSensor::State startState, stopState; + + measureSensors(startState, stopState); + + for (unsigned sensor = 0; sensor < PowerSensor::MAX_SENSORS; sensor ++) + if (powerSensor->inUse(sensor)) + std::cout << "sensor: " << sensor << ", " + "volt: " << powerSensor->getVolt(sensor) << " V, " + "type: " << type(sensor) << ", " + "null level: " << powerSensor->getNullLevel(sensor) << " W, " + "current usage: " << Watt(startState, stopState, sensor) << " W" << std::endl; + else + std::cout << "sensor: " << sensor << ", off" << std::endl; +} + + +void usage(char *argv[]) +{ + std::cerr << "usage: " << argv[0] << " [-d device] [-s sensor] [-t type] [-v volt] [-a | -n nullLevel] [-o] [-p]" << std::endl; + std::cerr << "-d selects the device (default: /dev/ttyACM0)" << std::endl; + std::cerr << "-s selects the sensor (0-4)" << std::endl; + std::cerr << "-t selects the sensor type, (one of ACS712-5, ACS712-20, ACS712-30, or a Volt-Per-Ampere value)" << std::endl; + std::cerr << "-v sets the voltage level" << std::endl; + std::cerr << "-a auto-calibrates the null level" << std::endl; + std::cerr << "-n manually sets the null level (the amount of Watt to be added)" << std::endl; + std::cerr << "-o turns off a sensor" << std::endl; + std::cerr << "-p prints configured values" << std::endl; + std::cerr << "example: " << argv[0] << " -d/dev/ttyACM0 -s0 -tACS712-20 -v12 -a -s1 -tACS712-5 -v3.3 -a -s2 -tACS712-20 -v12 -a -s3 -o -s4 -o -p" << std::endl; + exit(1); +} + + +int main(int argc, char *argv[]) +{ + for (int opt; (opt = getopt(argc, argv, "ad:n:ops:t:v:")) >= 0;) { + switch (opt) { + case 'a': checkPowerSensor(); + autoCalibrate(); + break; + + case 'd': powerSensor = std::unique_ptr<PowerSensor::PowerSensor>(new PowerSensor::PowerSensor(optarg)); + break; + + case 'n': checkPowerSensor()->setNullLevel(sensor, atof(optarg)); + break; + + case 'o': checkPowerSensor()->setVolt(sensor, 0); + break; + + case 'p': checkPowerSensor(); + print(); + break; + + case 's': sensor = atoi(optarg); + break; + + case 't': checkPowerSensor()->setType(sensor, convertType(optarg)); + break; + + case 'v': checkPowerSensor()->setVolt(sensor, atof(optarg)); + break; + + default: usage(argv); + } + } + + if (optind < argc) + usage(argv); + + return 0; +} diff --git a/psrun.cc b/psrun.cc new file mode 100644 index 0000000000000000000000000000000000000000..7f3fea3325039b22f99a09632df4a95afc084ffd --- /dev/null +++ b/psrun.cc @@ -0,0 +1,88 @@ +// 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 <iostream> + +#include <inttypes.h> +#include <sys/wait.h> +#include <unistd.h> + + +void usage(char *argv[]) +{ + std::cerr << "usage: " << argv[0] << " [-d device] [-f dump_file] [-s sensor] -- command [args]" << std::endl; + exit(1); +} + + +int main(int argc, char *argv[]) +{ + const char *device = "/dev/ttyACM0", *dumpFileName = 0; + int sensor = -1; + + for (int opt; (opt = getopt(argc, argv, "d:f:s:")) >= 0;) { + switch (opt) { + case 'd': device = optarg; + break; + + case 'f': dumpFileName = optarg; + break; + + case 's': sensor = atoi(optarg); + break; + + default: usage(argv); + } + } + + if (optind >= argc) + usage(argv); + + PowerSensor::PowerSensor powerSensor(device); + powerSensor.dump(dumpFileName); + PowerSensor::State startState = powerSensor.read(); + int retval; + + switch (fork()) { + case -1: perror("fork"); + exit(1); + + case 0: execvp(argv[optind], argv + optind); + perror("execvp"); + exit(1); + + default: if (wait(&retval) < 0) { + perror("wait"); + exit(1); + } + } + + PowerSensor::State stopState = powerSensor.read(); + + std::cout << + PowerSensor::seconds(startState, stopState) << " s, " << + PowerSensor::Joules(startState, stopState, sensor) << " J, " << + PowerSensor::Watt(startState, stopState, sensor) << " W" << + std::endl; + + return retval; +} diff --git a/pstest.cc b/pstest.cc new file mode 100644 index 0000000000000000000000000000000000000000..c5c2136d0af3d972adee9fdf3accb43b151ce3b7 --- /dev/null +++ b/pstest.cc @@ -0,0 +1,79 @@ +// 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 <iostream> + +#include <inttypes.h> +#include <unistd.h> + +#define MAX_MICRO_SECONDS 4000000 + + +void usage(char *argv[]) +{ + std::cerr << "usage: " << argv[0] << " [-d device] [-f dump_file] [-s sensor]" << std::endl; + exit(1); +} + + +int main(int argc, char *argv[]) +{ + const char *device = "/dev/ttyACM0", *dumpFileName = 0; + int sensor = -1; + + for (int opt; (opt = getopt(argc, argv, "d:f:s:")) >= 0;) { + switch (opt) { + case 'd': device = optarg; + break; + + case 'f': dumpFileName = optarg; + break; + + case 's': sensor = atoi(optarg); + break; + + default: usage(argv); + } + } + + if (optind < argc) + usage(argv); + + PowerSensor::PowerSensor powerSensor(device); + powerSensor.dump(dumpFileName); + + 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], sensor) << " J, " << + PowerSensor::Watt(states[i ^ 1], states[i], sensor) << " W" << + std::endl; + } + + return 0; +}