From 9c4ecb96f8eb05d44786fe75d5fd0fb8d288b401 Mon Sep 17 00:00:00 2001 From: Sam Moore Date: Sun, 22 Sep 2013 12:03:38 +0800 Subject: [PATCH] Fix ADC sampling - Fixed ADC_Read function - The path to the ADC data files is generally different (hooray) - Modified run.sh to work it out and pass to the program - run.sh also loads kernel modules, etc --- server/actuator.c | 1 + server/bbb_pin.c | 71 +++++++++++++++++++++++------------------------ server/bbb_pin.h | 2 +- server/main.c | 33 ++++++++++++++++++++-- server/options.h | 3 ++ server/run.sh | 32 ++++++++++++++++++++- server/sensor.c | 6 ++-- 7 files changed, 104 insertions(+), 44 deletions(-) diff --git a/server/actuator.c b/server/actuator.c index 50a27de..6d544f2 100644 --- a/server/actuator.c +++ b/server/actuator.c @@ -32,6 +32,7 @@ void Actuator_Init() // Initialise pins used GPIO_Export(GPIO1_16); PWM_Export(EHRPWM0A); + PWM_Export(EHRPWM0B); } diff --git a/server/bbb_pin.c b/server/bbb_pin.c index f8ba011..39f6f1f 100644 --- a/server/bbb_pin.c +++ b/server/bbb_pin.c @@ -9,6 +9,8 @@ #include #include #include +#include +#include "options.h" /** * Structure to represent a GPIO pin @@ -26,7 +28,7 @@ typedef struct */ typedef struct { - FILE * file_value; + int fd_value; } ADC_Pin; /** @@ -129,7 +131,7 @@ void PWM_Export(int pin) if (export == NULL) Fatal("Couldn't open %s to export PWM pin %d - %s", g_buffer, pin, strerror(errno)); - fprintf(export, "%d", pin); + fprintf(export, "%d\n", pin); fclose(export); // Open file descriptors @@ -194,22 +196,14 @@ void PWM_Unexport(int pin) */ void ADC_Export() { - - FILE * export = fopen(ADC_EXPORT_PATH, "w"); - if (export == NULL) - Fatal("Couldn't open %s to export ADCs - %s", ADC_EXPORT_PATH, strerror(errno)); - - fprintf(export, "cape-bone-iio"); - fclose(export); - for (int i = 0; i < ADC_NUM_PINS; ++i) { - sprintf(g_buffer, "%s/AIN%d", ADC_DEVICE_PATH, i); - g_adc[i].file_value = fopen(g_buffer, "r"); - if (g_adc[i].file_value == NULL) + sprintf(g_buffer, "%s/AIN%d", g_options.adc_device_path, i); + g_adc[i].fd_value = open(g_buffer, O_RDONLY); + if (g_adc[i].fd_value < 0) Fatal("Couldn't open ADC %d device file %s - %s", i, g_buffer, strerror(errno)); - setbuf(g_adc[i].file_value, NULL); + //setbuf(g_adc[i].file_value, NULL); } } @@ -220,7 +214,7 @@ void ADC_Export() void ADC_Unexport() { for (int i = 0; i < ADC_NUM_PINS; ++i) - fclose(g_adc[i].file_value); + close(g_adc[i].fd_value); } /** @@ -229,11 +223,11 @@ void ADC_Unexport() */ void GPIO_Set(int pin, bool value) { - if (pwrite(g_gpio[pin].fd_direction, "out", 3*sizeof(char), 0) != 3) + if (pwrite(g_gpio[pin].fd_direction, "out", 3, 0) != 3) Fatal("Couldn't set GPIO %d direction - %s", pin, strerror(errno)); char c = '0' + (value); - if (pwrite(g_gpio[pin].fd_value, &c, 1*sizeof(char), 0) != 1) + if (pwrite(g_gpio[pin].fd_value, &c, 1, 0) != 1) Fatal("Couldn't read GPIO %d value - %s", pin, strerror(errno)); } @@ -244,10 +238,10 @@ void GPIO_Set(int pin, bool value) */ bool GPIO_Read(int pin) { - if (pwrite(g_gpio[pin].fd_direction, "in", 2*sizeof(char), 0) != 2) + if (pwrite(g_gpio[pin].fd_direction, "in", 2, 0) != 2) Fatal("Couldn't set GPIO %d direction - %s", pin, strerror(errno)); char c = '0'; - if (pread(g_gpio[pin].fd_value, &c, 1*sizeof(char), 0) != 1) + if (pread(g_gpio[pin].fd_value, &c, 1, 0) != 1) Fatal("Couldn't read GPIO %d value - %s", pin, strerror(errno)); return (c == '1'); @@ -264,11 +258,11 @@ bool GPIO_Read(int pin) void PWM_Set(int pin, bool polarity, long period, long duty) { // Have to stop PWM before changing it - if (pwrite(g_pwm[pin].fd_run, "0", 1*sizeof(char), 0) != 1) + if (pwrite(g_pwm[pin].fd_run, "0", 1, 0) != 1) Fatal("Couldn't stop PWM %d - %s", pin, strerror(errno)); char c = '0' + polarity; - if (pwrite(g_pwm[pin].fd_polarity, &c, 1*sizeof(char), 0) != 1) + if (pwrite(g_pwm[pin].fd_polarity, &c, 1, 0) != 1) Fatal("Couldn't set PWM %d polarity - %s", pin, strerror(errno)); @@ -281,7 +275,7 @@ void PWM_Set(int pin, bool polarity, long period, long duty) if (fprintf(g_pwm[pin].file_period, "%lu", period) == 0) Fatal("Couldn't set period for PWM %d - %s", pin, strerror(errno)); - if (pwrite(g_pwm[pin].fd_run, "1", 1*sizeof(char), 0) != 1) + if (pwrite(g_pwm[pin].fd_run, "1", 1, 0) != 1) Fatal("Couldn't start PWM %d - %s", pin, strerror(errno)); } @@ -292,7 +286,7 @@ void PWM_Set(int pin, bool polarity, long period, long duty) */ void PWM_Stop(int pin) { - if (pwrite(g_pwm[pin].fd_run, "0", 1*sizeof(char), 0) != 1) + if (pwrite(g_pwm[pin].fd_run, "0", 1, 0) != 1) Fatal("Couldn't stop PWM %d - %s", pin, strerror(errno)); } @@ -302,25 +296,28 @@ void PWM_Stop(int pin) * @param id - The ID of the ADC pin to read * @returns - The reading of the ADC channel */ -long ADC_Read(int id) +int ADC_Read(int id) { - - //Log(LOGDEBUG, "Called for pin %d", id); - char adc_val[ADC_DIGITS] = ""; - rewind(g_adc[id].file_value); - fgets(adc_val, sizeof(adc_val)/sizeof(char), g_adc[id].file_value); - for(int i = ADC_DIGITS-1; i > 0; --i) + char adc_str[ADC_DIGITS] = ""; + lseek(g_adc[id].fd_value, 0, SEEK_SET); + + int i = 0; + for (i = 0; i < ADC_DIGITS-1; ++i) { - if (adc_val[i] == '\n') - adc_val[i] = '\0'; + if (read(g_adc[id].fd_value, adc_str+i, 1) != 1) + break; + if (adc_str[i] == '\n') + { + adc_str[i] = '\0'; + break; + } } char * end; - long val = strtol(adc_val, &end, 10); + int val = strtol(adc_str, &end, 10); if (*end != '\0') { - Log(LOGERR, "Reading ADC%d gives %s - invalid!", id, adc_val); - } - //Log(LOGDEBUG, "Returns %lu", val); - return val; + Log(LOGERR, "Read non integer from ADC %d - %s", id, adc_str); + } + return val; } diff --git a/server/bbb_pin.h b/server/bbb_pin.h index 472a917..04c02b6 100644 --- a/server/bbb_pin.h +++ b/server/bbb_pin.h @@ -24,7 +24,7 @@ extern void ADC_Unexport(); extern bool GPIO_Read(int pin); extern void GPIO_Set(int pin, bool value); -extern long ADC_Read(int pin); +extern int ADC_Read(int pin); extern void PWM_Set(int pin, bool polarity, long period, long duty); // period and duty are in ns extern void PWM_Stop(int pin); diff --git a/server/main.c b/server/main.c index c032eb1..930b8b0 100644 --- a/server/main.c +++ b/server/main.c @@ -9,6 +9,7 @@ #include "sensor.h" #include "actuator.h" #include "control.h" +#include "bbb_pin_defines.h" // --- Standard headers --- // #include // for system logging @@ -29,7 +30,32 @@ void ParseArguments(int argc, char ** argv) g_options.program = argv[0]; // program name g_options.verbosity = LOGDEBUG; // default log level gettimeofday(&(g_options.start_time), NULL); // Start time + g_options.adc_device_path = ADC_DEVICE_PATH; Log(LOGDEBUG, "Called as %s with %d arguments.", g_options.program, argc); + + for (int i = 1; i < argc; ++i) + { + if (argv[i][0] != '-') + Fatal("Unexpected argv[%d] - %s", i, argv[i]); + + if (i+1 >= argc || argv[i+1][0] == '-') + Fatal("No argument following switch %s", argv[i]); + + if (strlen(argv[i]) > 2) + Fatal("Human readable switches are not supported."); + + switch (argv[i][1]) + { + case 'a': + g_options.adc_device_path = argv[i+1]; + Log(LOGINFO, "ADC Device Path: %s", argv[i+1]); + ++i; + break; + default: + Fatal("Unrecognised switch %s", argv[i]); + break; + } + } } /** @@ -67,11 +93,14 @@ void Cleanup() */ int main(int argc, char ** argv) { + // Open log before calling ParseArguments (since ParseArguments may call the Log functions) + openlog("mctxserv", LOG_PID | LOG_PERROR, LOG_USER); + Log(LOGINFO, "Server started"); + ParseArguments(argc, argv); //Open the system log - openlog("mctxserv", LOG_PID | LOG_PERROR, LOG_USER); - Log(LOGINFO, "Server started"); + // signal handler //TODO: Make this work /* diff --git a/server/options.h b/server/options.h index a20e0e1..0416dd5 100644 --- a/server/options.h +++ b/server/options.h @@ -19,6 +19,9 @@ typedef struct /** Time at which program exits **/ struct timeval end_time; + /** Path to ADC files **/ + char * adc_device_path; + } Options; /** The only instance of the Options struct **/ diff --git a/server/run.sh b/server/run.sh index aafc5d1..be6d4cf 100755 --- a/server/run.sh +++ b/server/run.sh @@ -3,4 +3,34 @@ #spawn-fcgi -p9005 -n ./valgrind.sh # Use this to run the server normally #./stream & -spawn-fcgi -p9005 -n ./server + +# Check running as root +if [ "$(whoami)" != "root" ]; then + (echo "Run $0 as root.") 1>&2 + exit 1 +fi + +# Check existence of program +if [ ! -e "server" ]; then + (echo "Rebuild server.") 1>&2; + exit 1 +fi + +# Identify cape-manager slots +slot=$(echo /sys/devices/bone_capemgr.*/slots | awk '{print $1}') + +# Load PWM module +modprobe pwm_test +(echo am33xx_pwm > $slot) 1>&2 >> /dev/null + +# Load ADCs +(echo cape-bone-iio > $slot) 1>&2 >> /dev/null +# Find adc_device_path +# NOTE: This has to be passed as a parameter, because it is not always the same. For some unfathomable reason. Hooray. +adc_device_path=$(dirname $(find /sys -name *AIN0)) + + +# Run the program with parameters +# TODO: Can tell spawn-fcgi to run the program as an unprivelaged user? +# But first will have to work out how to set PWM/GPIO as unprivelaged user +spawn-fcgi -p9005 -n -- ./server -a "$adc_device_path" diff --git a/server/sensor.c b/server/sensor.c index 9d0b33c..28c3f5e 100644 --- a/server/sensor.c +++ b/server/sensor.c @@ -138,12 +138,12 @@ void Sensor_CheckData(SensorId id, double value) { if( value > thresholds[id].max_error || value < thresholds[id].min_error) { - Log(LOGERR, "Sensor %s is above or below its safety value of %f or %f\n", g_sensor_names[id],thresholds[id].max_error, thresholds[id].min_error); + Log(LOGERR, "Sensor %s at %f is above or below its safety value of %f or %f\n", value, g_sensor_names[id],thresholds[id].max_error, thresholds[id].min_error); //new function that stops actuators? } else if( value > thresholds[id].max_warn || value < thresholds[id].min_warn) { - Log(LOGWARN, "Sensor %s is above or below its warning value of %f or %f\n", g_sensor_names[id],thresholds[id].max_warn, thresholds[id].min_warn); + Log(LOGWARN, "Sensor %s at %f is above or below its warning value of %f or %f\n", value, g_sensor_names[id],thresholds[id].max_warn, thresholds[id].min_warn); } } @@ -173,7 +173,7 @@ bool Sensor_Read(Sensor * s, DataPoint * d) static bool set = false; GPIO_Set(GPIO0_30, true); - d->value = (double)ADC_Read(ADC0); //ADC #0 on the Beaglebone + d->value = 0;//(double)ADC_Read(ADC0); //ADC #0 on the Beaglebone //Log(LOGDEBUG, "Got value %f from ADC0", d->value); GPIO_Set(GPIO0_30, false); set = !set; -- 2.20.1