Merge branch 'master' of https://github.com/szmoore/MCTX3420.git
authorJeremy Tan <[email protected]>
Sun, 22 Sep 2013 00:43:17 +0000 (08:43 +0800)
committerJeremy Tan <[email protected]>
Sun, 22 Sep 2013 00:43:17 +0000 (08:43 +0800)
20 files changed:
BBB code/Actuator_SetValue_real.c
BBB code/Actuator_SetValue_real2.c [new file with mode: 0644]
BBB code/GetData_real.c
BBB code/gpio.c [new file with mode: 0644]
BBB code/gpio.h [new file with mode: 0644]
BBB code/pwm.c
BBB code/pwm.h
irc/log
server/Makefile
server/actuator.c
server/actuator.h
server/bbb_pin.c [new file with mode: 0644]
server/bbb_pin.h [new file with mode: 0644]
server/bbb_pin_defines.h [new file with mode: 0644]
server/fastcgi.c
server/log.c
server/log.h
server/sensor.c
server/sensor.h
web/gui.js

index e83020a..fe5e3c5 100644 (file)
@@ -1,13 +1,14 @@
 #include "pwm.h"
 
 char pin_dir = "/sys/class/gpio/gpio";         //move these
-int pwm_active = 0;
 
 /** Sets a GPIO pin to the desired value
 *      @param value - the value (1 or 0) to write to the pin
 *      @param pin_num - the number of the pin (refer to electronics team)
 */
 
+//also need to export and set pin direction
+
 void SetPin(int value, int pin_num) {
        int pin;
        char buffer[10];
diff --git a/BBB code/Actuator_SetValue_real2.c b/BBB code/Actuator_SetValue_real2.c
new file mode 100644 (file)
index 0000000..791de1e
--- /dev/null
@@ -0,0 +1,55 @@
+#include "gpio.h"
+#include "pwm.h"
+
+void Actuator_SetValue(Actuator * a, double value)
+{
+       // Set time stamp
+       struct timeval t;
+       gettimeofday(&t, NULL);
+
+       DataPoint d = {TIMEVAL_DIFF(t, g_options.start_time), value};
+       switch (a->id)
+       {
+               case ACTUATOR_TEST0:                    //LED actuator test code, should blink onboard LED next to Ethernet port
+                       FILE *LEDHandle = NULL;         //code reference: http://learnbuildshare.wordpress.com/2013/05/19/beaglebone-black-controlling-user-leds-using-c/
+                       char *LEDBrightness = "/sys/class/leds/beaglebone\:green\:usr0/brightness";
+                       if(value == 1) {
+                               if((LEDHandle = fopen(LEDBrightness, "r+")) != NULL) {
+                                       fwrite("1", sizeof(char), 1, LEDHandle);
+                                       fclose(LEDHandle);
+                               }
+                       else if(value == 0) {
+                               if((LEDHandle = fopen(LEDBrightness, "r+")) != NULL) {
+                                       fwrite("0", sizeof(char), 1, LEDHandle);
+                                       fclose(LEDHandle);
+                       }
+                       else perror("Pin value should be 1 or 0");
+                       break;
+               case ACTUATOR_TEST1:
+                       // Quick actuator function for testing pins
+                       // GPIOPin can be either passed as an argument, or defined here (as pins won't change)
+                       // First way is better and more generalised
+                       int GPIOPin = 13;
+                       // Modify this to only export on first run, unexport on shutdown
+                       pinExport(setValue, GPIOString);
+                       pinDirection(GPIODirection, setValue);
+                       pinSet(value, GPIOValue, setValue);
+                       pinUnexport(setValue, GPIOString);
+                       break;
+               case ACTUATOR_TEST2:
+                       if (pwminit == 0) {                                     //if inactive, start the pwm module
+                               pwm_init();
+                       }
+                       if (pwmstart == 0) {
+                               pwm_start();
+                               pwm_set_period(FREQ);                           //50Hz defined in pwm header file
+                       }
+                       if(value >= 0 && value <= 1000) {
+                               double duty = value/1000 * 100;         //convert pressure to duty percentage
+                               pwm_set_duty((int)duty);                        //set duty percentage for actuator
+                       }
+       }
+       Log(LOGDEBUG, "Actuator %s set to %f", g_actuator_names[a->id], value);
+       // Record the value
+       Data_Save(&(a->data_file), &d, 1);
+}
\ No newline at end of file
index f52427c..c724e62 100644 (file)
@@ -1,64 +1,4 @@
-char adc_dir = "/sys/devices/platform/tsc/ain";
-char pin_dir = "/sys/class/gpio/gpio";
-
-/** Open an ADC and return the voltage value from it
-*      @param adc_num - ADC number, ranges from 0 to 7 on the Beaglebone
-       @return the converted voltage value if successful
-*/
-
-//TODO: create a function to lookup the ADC or pin number instead of manually
-//             specifying it here (so we can keep all the numbers in one place)
-
-int OpenAnalog(int adc_num)
-{
-       char adc_path[40];
-       snprintf(adc_path, sizeof(adc_path), "%s%d", adc_dir, adc_num);         //construct ADC path
-       int sensor = open(adc_path, O_RDONLY);
-       char buffer[128];                                                               //I think ADCs are only 12 bits (0-4096)
-       int read = read(sensor, buffer, sizeof(buffer); //buffer can probably be smaller
-       if (read != -1) {
-               buffer[read] = NULL;
-               int value = atoi(buffer);
-               double convert = (value/4096) * 1000;           //random conversion factor, will be different for each sensor
-               //lseek(sensor, 0, 0);
-               close(sensor);
-               return convert;
-       }
-       else {
-               perror("Failed to get value from sensor");
-               close(sensor);
-               return -1;
-       }
-}
-
-/** Open a digital pin and return the value from it
-*      @param pin_num - pin number, specified by electronics team
-       @return 1 or 0 if reading was successful
-*/
-
-int OpenDigital(int pin_num)
-{
-       char pin_path[40];
-       snprintf(pin_path, sizeof(pin_path), "%s%d%s", pin_dir, pin_num, "/value");     //construct pin path
-       int pin = open(pin_path, O_RDONLY);
-       char ch;
-       lseek(fd, 0, SEEK_SET);
-       int read = read(pin, &ch, sizeof(ch);
-       if (read != -1) {
-               if (ch != '0') {
-                       close(pin);
-                       return 1;
-               }
-               else {
-                       close(pin);
-                       return 0;
-               }
-       else {
-               perror("Failed to get value from pin");
-               close(pin);
-               return -1;
-       }
-}
+#include "gpio.h"
 
 /**
  * Read a DataPoint from a Sensor; block until value is read
@@ -78,11 +18,11 @@ bool Sensor_Read(Sensor * s, DataPoint * d)
        switch (s->id)
        {
                case ANALOG_TEST0:
-                       d->value = OpenAnalog(0);       //ADC #0 on the Beaglebone
+                       d->value = ADCRead(0);  //ADC #0 on the Beaglebone
                        break;
                case ANALOG_TEST1:
                {
-                       d->value = OpenAnalog(1);
+                       d->value = ADCRead(1);
                        break;
                }
                case ANALOG_FAIL0:
@@ -90,10 +30,10 @@ bool Sensor_Read(Sensor * s, DataPoint * d)
                        //Gives a value between -5 and 5
                        break;
                case DIGITAL_TEST0:
-                       d->value = openDigital(0);      //replace 0 with correct pin number
+                       d->value = pinRead(0);  //replace 0 with correct pin number
                        break;
                case DIGITAL_TEST1:
-                       d->value = openDigital(1);      //replace 1 with correct pin number
+                       d->value = pinRead(1);  //replace 1 with correct pin number
                        break;
                case DIGITAL_FAIL0:
                        if( rand() % 100 > 98)
diff --git a/BBB code/gpio.c b/BBB code/gpio.c
new file mode 100644 (file)
index 0000000..65f1a51
--- /dev/null
@@ -0,0 +1,128 @@
+#include "gpio.h"
+
+void pinExport(int GPIOPin) {
+       FILE *myOutputHandle = NULL;
+       char GPIOString[4];
+       char setValue[4];
+       sprintf(GPIOString, "%d", GPIOPin);
+       if ((myOutputHandle = fopen(exportPath, "ab")) == NULL){
+               Log(LOGERR, "Unable to export GPIO pin %f\n", GPIOPin);
+       }
+       strcpy(setValue, GPIOString);
+       fwrite(&setValue, sizeof(char), 2, myOutputHandle);
+       fclose(myOutputHandle);
+}
+
+void pinDirection(int GPIOPin, int io) {
+       char setValue[4];
+       char GPIODirection[64];
+       FILE *myOutputHandle = NULL;
+       snprintf(GPIODirection, sizeof(GPIODirection), "%s%d%s", directionPath, GPIOPin, "/direction");
+       if ((myOutputHandle = fopen(GPIODirection, "rb+")) == NULL){
+               Log(LOGERR, "Unable to open direction handle for pin %f\n", GPIOPin);
+       }
+       if (io == 1) {
+               strcpy(setValue,"out");
+               fwrite(&setValue, sizeof(char), 3, myOutputHandle);
+       else if (io == 0) {
+               strcpy(setValue,"in");
+               fwrite(&setValue, sizeof(char), 2, myOutputHandle);
+       else Log(LOGERR, "GPIO direction must be 1 or 0\n");
+       fclose(myOutputHandle);
+}
+
+void pinSet(double value, int GPIOPin) {
+       int val = (int)value;
+       char GPIOValue[64];
+       char setValue[4];
+       FILE *myOutputHandle = NULL;
+       snprintf(GPIOValue, sizeof(GPIOValue), "%s%d%s", valuePath, GPIOPin, "/value");
+       if (val == 1) {
+               if ((myOutputHandle = fopen(GPIOValue, "rb+")) == NULL){
+                       Log(LOGERR, "Unable to open value handle for pin %f\n", GPIOPin);
+               }
+               strcpy(setValue, "1"); // Set value high
+               fwrite(&setValue, sizeof(char), 1, myOutputHandle);
+       }
+       else if (val == 0){
+               if ((myOutputHandle = fopen(GPIOValue, "rb+")) == NULL){
+                       Log(LOGERR, "Unable to open value handle for pin %f\n", GPIOPin);
+               }
+               strcpy(setValue, "0"); // Set value low
+               fwrite(&setValue, sizeof(char), 1, myOutputHandle);
+       }
+       else Log(LOGERR, "GPIO value must be 1 or 0\n");
+       fclose(myOutputHandle);
+}
+
+/** Open an ADC and return the voltage value from it
+*      @param adc_num - ADC number, ranges from 0 to 7 on the Beaglebone
+       @return the converted voltage value if successful
+*/
+
+//TODO: create a function to lookup the ADC or pin number instead of manually
+//             specifying it here (so we can keep all the numbers in one place)
+
+int ADCRead(int adc_num)
+{
+       char adc_path[64];
+       snprintf(adc_path, sizeof(adc_path), "%s%d", ADCPath, adc_num);         // Construct ADC path
+       int sensor = open(adc_path, O_RDONLY);                                                          
+       char buffer[64];                                                                                                        // I think ADCs are only 12 bits (0-4096), buffer can probably be smaller
+       int read = read(sensor, buffer, sizeof(buffer);
+       if (read != -1) {
+               buffer[read] = NULL;
+               int value = atoi(buffer);
+               double convert = (value/4096) * 1000;                                                   // Random conversion factor, will be different for each sensor (get from datasheets)
+               // lseek(sensor, 0, 0); (I think this is uneeded as we are reopening the file on each sensor read; if sensor is read continously we'll need this
+               close(sensor);
+               return convert;
+       }
+       else {
+               Log(LOGERR, "Failed to get value from ADC %f\n", adc_num);
+               close(sensor);
+               return -1;
+       }
+}
+
+/** Open a digital pin and return the value from it
+*      @param pin_num - pin number, specified by electronics team
+       @return 1 or 0 if reading was successful
+*/
+
+int pinRead(int GPIOPin)
+{
+       char GPIOValue[64];
+       snprintf(GPIOValue, sizeof(GPIOValue), "%s%d%s", valuePath, GPIOPin, "/value"); //construct pin path
+       int pin = open(GPIOValue, O_RDONLY);
+       char ch;
+       lseek(fd, 0, SEEK_SET);
+       int read = read(pin, &ch, sizeof(ch);
+       if (read != -1) {
+               if (ch != '0') {
+                       close(pin);
+                       return 1;
+               }
+               else {
+                       close(pin);
+                       return 0;
+               }
+       else {
+               Log(LOGERR, "Failed to get value from pin %f\n", GPIOPin);
+               close(pin);
+               return -1;
+       }
+}
+
+void pinUnexport(int GPIOPin) {
+       char setValue[4];
+       char GPIOString[4];
+       sprintf(GPIOString, "%d", GPIOPin);
+       FILE *myOutputHandle = NULL;
+       if ((myOutputHandle = fopen(unexportPath, "ab")) == NULL) {
+               Log(LOGERR, "Couldn't unexport GPIO pin %f\n", GPIOPin);
+       }
+       strcpy(setValue, GPIOString);
+       fwrite(&setValue, sizeof(char), 2, myOutputHandle);
+       fclose(myOutputHandle);
+}
\ No newline at end of file
diff --git a/BBB code/gpio.h b/BBB code/gpio.h
new file mode 100644 (file)
index 0000000..1da8470
--- /dev/null
@@ -0,0 +1,24 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+#include <sched.h>
+#include <stdint.h>
+
+#define exportPath             "/sys/class/gpio/export";
+#define unexportPath   "/sys/class/gpio/unexport";
+#define valuePath              "/sys/class/gpio/gpio";
+#define directionPath  "/sys/class/gpio/gpio";
+#define ADCPath                "/sys/devices/platform/tsc/ain";
+
+void pinExport(int GPIOPin);
+void pinDirection(int GPIOPin, int io);
+void pinSet(double value, int GPIOPin);
+void pinUnexport(int GPIOPin);
+int pinRead(int GPIOPin);
+int ADCRead(int adc_num);
\ No newline at end of file
index b58873e..b86b07e 100644 (file)
@@ -11,8 +11,10 @@ can modify pwm variables through virtual filesystem:
 pwm drivers reference:
 http://processors.wiki.ti.com/index.php/AM335x_PWM_Driver%27s_Guide */
 
-void pwm_init(void)
-{
+static int pwminit = 0;
+static int pwmstart = 0;
+
+void pwm_init(void) {
     FILE *pwm_mux;
     int i;
     volatile uint32_t *epwmss1;
@@ -36,8 +38,8 @@ void pwm_init(void)
                epwmss1[OFFSET_1 / sizeof(uint32_t)] = 0x2;
                }
     close(fd);
-    
-    pwm_mux = fopen("/sys/kernel/debug/omap_mux/gpmc_a2", "w");
+    pwminit = 1;
+    pwm_mux = fopen(PWMMuxPath, "w");
     fprintf(pwm_mux, "6");                                                      // pwm is mux mode 6
     fclose(pwm_mux);
 }
@@ -46,41 +48,36 @@ void pwm_init(void)
 //depends how many pwm modules we have to run
 //TODO:
 
-void pwm_start(void)
-{
+void pwm_start(void) {
     FILE *pwm_run;
-    pwm_run = fopen("/sys/class/pwm/ehrpwm.1:0/run", "w");
+    pwm_run = fopen(PWMRunPath, "w");
     fprintf(pwm_run, "1");
     fclose(pwm_run);
+       pwmstart = 1;
 }
 
-void pwm_stop(void)
-{
+void pwm_stop(void) {
     FILE *pwm_run;
-    
-    pwm_run = fopen("/sys/class/pwm/ehrpwm.1:0/run", "w");
+    pwm_run = fopen(PWMRunPath, "w");
     fprintf(pwm_run, "0");
     fclose(pwm_run);
+       pwmstart = 0;
 }
 
 //duty_percent is just a regular percentage (i.e. 50 = 50%)
 
-void pwm_set_duty(int duty_percent)
-{
+void pwm_set_duty(int duty_percent) {
     FILE *pwm_duty;
-    
-    pwm_duty = fopen("/sys/class/pwm/ehrpwm.1:0/duty_percent", "w"); 
+    pwm_duty = fopen(PWMDutyPath, "w"); 
     fprintf(pwm_duty, "%d", duty_percent);
     fclose(pwm_duty);
 }
 
 //freq is just normal frequency (i.e. 100 = 100Hz)
 
-void pwm_set_period(int freq)
-{
+void pwm_set_period(int freq) {
     FILE *pwm_period;
-    
-    pwm_period = fopen("/sys/class/pwm/ehrpwm.1:0/period_freq", "w");
+    pwm_period = fopen(PWMFreqPath, "w");
     fprintf(pwm_period, "%d", freq);
     fclose(pwm_period);
 }
\ No newline at end of file
index 605095f..2c9411b 100644 (file)
 #include <sched.h>
 #include <stdint.h>
 
-#define START    0x44e00000    // see datasheet of AM335x
-#define LENGTH   1024
-#define OFFSET_1 0xcc          // offset of PWM1 clock (see datasheet of AM335x p.1018)
-#define FREQ    50                        //50Hz pwm frequency for pressure regulator
+#define START          0x44e00000    // see datasheet of AM335x
+#define LENGTH         1024
+#define OFFSET_1       0xcc          // offset of PWM1 clock (see datasheet of AM335x p.1018)
+#define FREQ           50                         //50Hz pwm frequency for pressure regulator
+#define PWMMuxPath     "/sys/kernel/debug/omap_mux/gpmc_a2"
+#define PWMRunPath     "/sys/class/pwm/ehrpwm.1:0/run"
+#define PWMDutyPath    "/sys/class/pwm/ehrpwm.1:0/duty_percent"
+#define PWMFreqPath    "/sys/class/pwm/ehrpwm.1:0/period_freq"
 
 void pwm_init(void);
 void pwm_start(void);
diff --git a/irc/log b/irc/log
index 87b7345..1370d76 100644 (file)
--- a/irc/log
+++ b/irc/log
 20:00 -!- MctxBot [[email protected]] has quit [Ping timeout]
 21:26 -!- MctxBot [[email protected]] has joined #mctxuwa_softdev
 22:58 -!- jtanx [[email protected]] has quit ["ChatZilla 0.9.90.1 [Firefox 23.0.1/20130814063812]"]
+--- Day changed Tue Sep 17 2013
+08:14 -!- jtanx [[email protected]] has joined #mctxuwa_softdev
+09:50 -!- jtanx [[email protected]] has quit ["ChatZilla 0.9.90.1 [Firefox 23.0.1/20130814063812]"]
+15:34 -!- jtanx [[email protected]] has joined #mctxuwa_softdev
+15:34 < jtanx> to run the software not as root, we need to at least add it to the 'video' group so it can access the webcam
+15:34 < jtanx> not sure about the sensors
+15:34 < jtanx> eg sudo usermod -a -G video debian
+15:38 < sam_moore> Ah, cool
+15:39 < sam_moore> I think I worked out how to get around the camera crashing without killing the rest of the program, won't implement it for a while though
+15:40 -!- MctxBot [[email protected]] has quit [EOF From client]
+15:43 -!- jtanx_ [[email protected]] has joined #mctxuwa_softdev
+15:48 -!- MctxBot [[email protected]] has joined #mctxuwa_softdev
+15:53 -!- jtanx [[email protected]] has quit [Ping timeout]
+15:57 -!- jtanx_ is now known as jtanx
+16:41 -!- jtanx [[email protected]] has quit [Ping timeout]
+16:46 -!- jtanx_ [[email protected]] has joined #mctxuwa_softdev
+16:46 -!- jtanx_ is now known as jtanx
+18:02 -!- jtanx [[email protected]] has quit ["ChatZilla 0.9.90.1 [Firefox 23.0.1/20130814063812]"]
+18:16 -!- jtanx [[email protected]] has joined #mctxuwa_softdev
+19:31 -!- MctxBot [[email protected]] has quit [Ping timeout]
+22:38 -!- MctxBot [[email protected]] has joined #mctxuwa_softdev
+22:49 -!- jtanx [[email protected]] has quit [Ping timeout]
+23:17 -!- Callum [[email protected]] has joined #mctxuwa_softdev
+23:18 < Callum> hey
+23:23 < sam_moore> Hi
+23:24 < Callum> do you know how to do the second question of that assignment?
+23:24 < Callum> https://docs.google.com/file/d/0B241H5liqVlnbHZETXRZX1Mwd1k/edit?usp=sharing
+23:25 < Callum> rather remember
+23:35 < sam_moore> Well, you can eliminate any epsilon^2 when you substitute those formulae for v into the formula for gamma
+23:35 < sam_moore> Then it has a really simple taylor expansion
+23:35 < Callum> i might have to hunt you down tomorrow to show me. or maybe il be able to think straight tomorrow.
+23:38 < sam_moore> You can express one of the epsilons in terms of the other one after that
+23:40 < sam_moore> I'm pretty busy tomorrow
+23:42 < Callum> mhmm. so no free time at all? coz im fairly free
+23:49 < sam_moore> Not from 8:00am until 5:00pm
+23:49 < Callum> ohwow. you are busy
+23:49 < Callum> im still unsure what im meant to be applyign the taylor expansion to
+23:53 < sam_moore> Substitute in the suggested formulae to gamma, simplify it, then apply a taylor expansion
+23:53 < sam_moore> Anyway, goodnight, good luck
+23:53 < Callum> night
+--- Day changed Wed Sep 18 2013
+00:07 -!- Callum [[email protected]] has quit [EOF From client]
+07:50 -!- jtanx [[email protected]] has joined #mctxuwa_softdev
+09:11 -!- jtanx [[email protected]] has quit ["ChatZilla 0.9.90.1 [Firefox 23.0.1/20130814063812]"]
+18:50 -!- jtanx [[email protected]] has joined #mctxuwa_softdev
+19:04 -!- MctxBot [[email protected]] has quit [Ping timeout]
+21:03 -!- jtanx [[email protected]] has quit ["ChatZilla 0.9.90.1 [Firefox 24.0/20130910160258]"]
+21:39 -!- MctxBot [[email protected]] has joined #mctxuwa_softdev
+--- Day changed Thu Sep 19 2013
+16:07 -!- jtanx [[email protected]] has joined #mctxuwa_softdev
+16:08 < jtanx> one thing I forgot to mention - the latest version on git uses syslog
+16:08 < jtanx> if you copy the config file (server-configs/rsyslog.d/* ??) to /etc/
+16:09 < jtanx> it will log to /var/log/mctx[something I can't remember].log
+16:10 < jtanx> i'm pretty sure you can also create a log file specifically for warning level and above (so it logs in three places, stderr, the normal log, and a special 'error' log), but I haven't set this up yet
+18:15 -!- MctxBot_ [[email protected]] has joined #mctxuwa_softdev
+18:17 -!- jtanx_ [[email protected]] has joined #mctxuwa_softdev
+18:17 < jtanx_> :0
+18:22 < sam_moore> ?
+18:30 -!- MctxBot [[email protected]] has quit [Ping timeout]
+18:31 -!- jtanx [[email protected]] has quit [Ping timeout]
+18:50 -!- jtanx_ is now known as jtanx
+19:11 -!- jtanx [[email protected]] has quit [Ping timeout]
+19:51 -!- jtanx [[email protected]] has joined #mctxuwa_softdev
+19:52 -!- MctxBot_ is now known as MctxBot
+20:24 < jtanx> I got the camera image to be updated in javascript instead: http://mctx.us.to:8080/test/
+20:25 < jtanx> right now it's updated around every ~400ms because my webcam is running through a usb1.1 link which seriously limits how fast it can update
+20:36 < jtanx> (its running on a pentium 3 computer)
+21:35 -!- jtanx [[email protected]] has quit ["ChatZilla 0.9.90.1 [Firefox 24.0/20130910160258]"]
+--- Day changed Fri Sep 20 2013
+15:38 -!- jtanx [[email protected]] has joined #mctxuwa_softdev
+15:53 -!- MctxBot [[email protected]] has quit [Ping timeout]
+18:02 < jtanx> this seems like an interesting option, at least for the cam that just shows the can explode:http://sourceforge.net/apps/mediawiki/mjpg-streamer/index.php?title=Main_Page
+18:51 < sam_moore> Cool
+18:51 < sam_moore> It, ah
+18:52 < sam_moore> Looks like we might have to recompile the kernel to get PWM working
+18:52 < sam_moore> Hooray
+18:52 < sam_moore> Kernel compiling
+18:52 < sam_moore> What could possibly go wrong?
+19:02 < jtanx> really??
+19:02 < jtanx> why....
+19:03 < jtanx> no am33xx_pwm module?
+19:04 < sam_moore> Not that I can tell
+19:05 < jtanx> well crap
+19:06 < sam_moore> Well... surely I can find a precompiled kernel somewhere
+19:06 < jtanx> it seems that stuff for the BBB is at a really premature stage
+19:07 < sam_moore> Yeah, RPi is much nicer
+19:07 < jtanx> the BBB is just too new..
+19:07 < sam_moore> What's the point of having fancy things like ADC and PWM...
+19:07 < sam_moore> If you can't actually use them without jumping through hoops
+19:07 < jtanx> hahaha
+19:07 < jtanx> were you referencing this, when you said we might have to recompile the kernel? https://groups.google.com/d/msg/beagleboard/wjbOVE6ItNg/AGYVRhYbTX8J
+19:08 < sam_moore> Yeah
+19:08 < sam_moore> ...
+19:08 < sam_moore> I wonder if I can take the kernel used by Angstrom and stick it in /boot
+19:08 < sam_moore> on the SD card
+19:09 < jtanx> ._.
+19:10 < jtanx> what about kernels from here
+19:10 < jtanx> http://rcn-ee.net/deb/precise-armhf/
+19:10 < jtanx> sorry
+19:10 < jtanx> http://rcn-ee.net/deb/wheezy-armhf/
+19:11 < jtanx> what's it currently running
+19:12 < sam_moore> 3.8.13-bone20
+19:13 < sam_moore> Try 3.8.13-bone28 ?
+19:15 < jtanx> what about v3.8.9-bone15
+19:15 < jtanx> oh wait
+19:15 < jtanx> ~.~
+19:15 < sam_moore> I wonder why the BBB developers didn't go with debian...
+19:15 < jtanx> v3.11.0-bone5
+19:15 < jtanx> yeah
+19:15 < jtanx> why angstrom, of all things
+19:15 < sam_moore> Is angstrom used anywhere else?
+19:16 < jtanx> dunno
+19:16 < sam_moore> Other embedded devices, heh
+19:16 < sam_moore> Everyone just has to use their own distro :P
+19:17 < sam_moore> I didn't see the .11 kernels, I'll try the latest one
+19:17 < jtanx> want to try the rc version? lol
+19:18 < jtanx> oh the rc versions are older than .11
+19:19 < jtanx> how does it work?
+19:19 < jtanx> do you just download from http://rcn-ee.net/deb/wheezy-armhf/v3.11.0-bone5/
+19:19 < jtanx> the .sh script and run it from the BBB?
+19:24 < sam_moore> I think so
+19:25 < sam_moore> Well... here goes nothing
+19:26 < sam_moore> Hopefully between 3.8 and 3.11 they actually enabled PWM by default...
+19:27 < sam_moore> It looks like install-me.sh downloads all the .deb files appropriately
+19:29 < sam_moore> It's creating files like: /lib/firmware/bone_pwm_P8_36-00
+19:29 < sam_moore> Which looks promising
+19:29 < sam_moore> Snoopy is not yet on fire
+19:29 < sam_moore> Which is promising
+19:29 < sam_moore> Rebooting and praying
+19:31 < sam_moore> And... it booted into 3.8.13-bone20 -_-
+19:31 < sam_moore> Tempted to just symlink that filename to the new kernel
+19:34 < sam_moore> The new kernel exists in /boot, but obviously there's some boot config that needs to get set
+19:39 < sam_moore> Ok, screw this, I'm making a symlink just to see if it works
+19:40 < jtanx> lol
+19:41 < jtanx> no grub
+19:43 < jtanx> did update-initramfs run?
+19:46 < jtanx> or maybe we need mkimage
+19:47 < jtanx> yeah probably need mkimage
+19:50 < sam_moore> Um, zImage is a symlink to the kernel
+19:50 < sam_moore> But regardless, the new one won't boot
+19:50 < sam_moore> Such a pain
+19:50 < sam_moore> I wonder if we can just toggle the GPIO pin fast enough to implement PWM
+19:56 < sam_moore> Using a decent oscilloscope, I read a 6us period when switching GPIO1_28 on/off as fast as possible
+19:59 < sam_moore> That
+19:59 < sam_moore> s like 166KHz
+19:59 < sam_moore> Heh
+19:59 < sam_moore> Maybe the sources you found were closing the file and reopening it?
+20:01 < sam_moore> Yeah, wow
+20:02 < sam_moore> Using fopen, fprintf and fclose each time takes the period to 224us
+20:02 < sam_moore> Or 4KHz
+20:03 < sam_moore> Also for future reference, that CRO in G19 is definitely broken; it's always a lovely square wave on the modern oscilloscope I'm testing with now
+20:12 < jtanx> haha ok
+20:13 < jtanx> but without kernel support your pwm signal won't be very accurate
+20:13 < sam_moore> Yeah, I suppose
+20:13 < jtanx> how come the new kernel won't boot?
+20:14 < sam_moore> No idea
+20:14 < jtanx> Hmm
+20:14 < jtanx> this lack of documentation on how you do such procedures is pretty crap
+20:15 < sam_moore> Yeah, kernel developers aren't great on documentation
+20:15 < jtanx> is the mkimage package present?
+20:15 < jtanx> if not, install it and try running the install-me script again
+20:16 < jtanx> from this: http://www.jeremycole.com/blog/2011/03/09/beagleboard-upgrading-from-debian-5-to-debian-6/
+20:16 < jtanx> it should be just running that install script and rebooting
+20:16 < sam_moore> Alright, uboot-mkimage I presume?
+20:16 < jtanx> i guess
+20:17 < jtanx> and update-initramfs?
+20:18 < jtanx> (just looking at what the install-me.sh script uses)
+20:18 < sam_moore> Oh, does the script not fail if packages it needs don't exist...
+20:18 < sam_moore> -_-
+20:19 < jtanx> a quick scan says nup
+20:24 < sam_moore> Already had initramfs-tools but not mkimage, so I'll try again
+20:27 < sam_moore> I should probably have focused on the ADC reading before PWM
+20:27 < sam_moore> We're definitely going to get asked about aliasing again
+20:28 < jtanx> urgh yeah
+20:28 < sam_moore> I don't have a signal generator here though
+20:28 < jtanx> this BBB has definitely not been designed with 'plug n play' in mind
+20:28 < sam_moore> Mmm
+20:29 < sam_moore> The Angstrom image would work for this stuff, but obviously has limitations in terms of the webserver stuff
+20:29 < sam_moore> But even with Angstrom you still have to go through a similar convoluted process to control pins
+20:30 < sam_moore> From what I can tell there are two ways to do it
+20:30 < sam_moore> SYSFS, which I can't find much documentation on
+20:30 < sam_moore> Which is the /sys/class/gpio/ stuff
+20:30 < sam_moore> Which actually seems more intuitive than the other way
+20:31 < sam_moore> That involves echoing a bunch of cruft to /sys/devices/cape-manager/slots/ or something similar
+20:31 < jtanx> hmm
+20:32 < sam_moore> There is a /sys/class/pwm
+20:32 < sam_moore> But unfortunately whatever you export it complains about
+20:32 < sam_moore> Probably because the kernel wasn't compiled with it enabled
+20:32 < jtanx> is this with the old kernel?
+20:32 < sam_moore> Yeah
+20:33 < sam_moore> Hangon, the new one's probably finished building by now
+20:34 < jtanx> we don't know if the new one has been compiled with pwm support though
+20:34 < sam_moore> Yeah
+20:36 < sam_moore> The diff between the config options for the kernels shows that the old one has a comment "CONFIG_EHRPWM_TEST is not set" and the newer one has no reference to it
+20:37 < sam_moore> ...
+20:37 < sam_moore> Someone at some point
+20:37 < sam_moore> Has realised that PWM was not enabled
+20:37 < sam_moore> And commented that it isn't enabled
+20:37 < sam_moore> WHY THE HELL DIDN'T THEY JUST ENABLE IT
+20:37 < jtanx> :P
+20:37 < sam_moore> Anyway it still booted off the old kernel
+20:37 < sam_moore> Dinner time
+20:38 < jtanx> ok
+20:57 -!- MctxBot [[email protected]] has joined #mctxuwa_softdev
+21:15 < sam_moore> http://www.eewiki.net/display/linuxonarm/BeagleBone+Black#BeagleBoneBlack-LinuxKernel
+21:15 < sam_moore> Looks promising
+21:16 < sam_moore> Hmm...
+21:17 < sam_moore> I'll try using 3.8 but building with the PWM
+21:18 < jtanx> building from source - fun fun :P
+21:19 < sam_moore> Well in theory I just change a config option
+21:19 < jtanx> yeah
+21:19 < sam_moore> When that doesn't work and I have to modify the source, that's when the fun begins
+21:19 < jtanx> let's just hope it works
+21:19 < sam_moore> Yeah, if it doesn't we're (beagle) boned
+21:19 < jtanx> oh while you're at it, figure out how to enable the ethernet-over-usb feature
+21:19 < sam_moore> Haha
+21:20 < jtanx> loljk
+21:25 < sam_moore> Hmmm... compiling a kernel is going to take a while
+21:26 < sam_moore> Ergh, why am I running it on this Pentium D
+21:30 < sam_moore> Hmmm, more troubling... why does a debian wheezy server have OpenSUSE sources in sources.list
+21:30 < sam_moore> Oh well, not my problem
+21:33 < jtanx> heh
+21:33 < sam_moore> How the hell are we going to explain this in the progress report...
+21:34 < sam_moore> Also, I didn't fully understand, why can't you use the same image for multiple BBB?
+21:34 < sam_moore> Are we going to have to do this all again for the other BBB?
+21:34 < sam_moore> Spike I mean
+21:37 < jtanx> no idea
+21:38 < jtanx> without some sort of debugging cable to see what happens when it boots, who knows
+21:38 < sam_moore> :S
+21:39 < sam_moore> I love how git gets to the head of the branch
+21:39 < sam_moore> By starting at the initial commit
+21:39 < sam_moore> And going through every commit and changing the file
+21:42 < sam_moore> It hasn't started building yet
+21:42 < sam_moore> And the way you customise the build...
+21:42 < sam_moore> Is to build it with the defaults, so that the options file exists, then change the options, then build it again -_-
+21:43 < jtanx> ಠ ಠ
+21:43 < sam_moore> Oh well, I have to go home, I'll try finish this tomorrow
+21:43 < sam_moore> Bye
+21:43 < jtanx> ok
+21:43 < jtanx> bye
+23:20 -!- jtanx [[email protected]] has quit ["ChatZilla 0.9.90.1 [Firefox 24.0/20130910160258]"]
+--- Day changed Sat Sep 21 2013
+08:42 -!- jtanx [[email protected]] has joined #mctxuwa_softdev
+11:23 < sam_moore> http://hipstercircuits.com/enable-pwm-on-beaglebone-with-device-tree-overlays/
+11:23 < sam_moore> So... according to this I should add pwm_test as a kernel module
+11:24 < sam_moore> "This is it. It is now three o’clock in the morning and I have not slept or eaten in two days. My neck is sore, my ass has fallen asleep and my organs are screaming “slow down, man”. I no longer see [CC]s, [LD]s and [AS]s, I only see blondes, brunettes and redheads flashing before my eyes. With my last ounce of energy I barely manage to type in “reboot” as my face hits the keyboard. And that is when it happens.."
+11:25 < sam_moore> Ummm
+11:25 < sam_moore> It's awesome that this guy has solved the problem (I think)
+11:26 < sam_moore> But a bit depressing that it still isn't in the official kernel
+11:29 < sam_moore> I think most people just give up and use Angstrom, which is tempting
+11:30 < sam_moore> I still have that HTTP server code... :P
+11:45 < sam_moore> Looks like Robert C Nelson's 3.8 kernel does have a pwm_test module
+11:45 < sam_moore> Maybe the image you used just had an out of date kernel?
+11:45 -!- Irssi: #mctxuwa_softdev: Total of 3 nicks [0 ops, 0 halfops, 0 voices, 3 normal]
+11:51 < jtanx> hmm
+11:51 < jtanx> no idea
+11:51 < jtanx> it was made in july I think and it uses those rcn kernels
+11:51 < jtanx> We could always use lighttp
+11:51 < jtanx> lighttpd on angstrom if necessary
+11:52 < jtanx> lighttpd and install mod_fastcgi
+11:55 < jtanx> ok so the image uses 3.8.13-bone20, so maybe it wasn't enabled in that version, but it now is in 3.8.13-bone28?
+12:02 < sam_moore> I've just built 3.8.13-bone28 and the module pwm_test exists
+12:03 < sam_moore> ... I also copied the code from that guy's blog as pwm_test2 just in case :P
+12:03 < sam_moore> I'll have to test it later, but at least we have the kernel module
+12:08 < jtanx> nice
+12:39 < jtanx> ohhhhh I know why it didn't work from one bbb to the next, using the same image
+12:39 < jtanx> When you boot for the first time, it assigns the ethernet port eth0
+12:39 < jtanx> when you then take it out and boot it on a different BBB
+12:40 < jtanx> because the ethernet device has a different id, it gets assigned to say eth1
+12:40 < jtanx> and because you don't have any config for eth1 in your network config, there's no internet access
+12:40 < jtanx> http://www.eewiki.net/display/linuxonarm/BeagleBone#BeagleBone-Networking:UsingasharedSDcardwithMultipleBeagleBone
+12:41 < jtanx> should fix that
+13:21 -!- jtanx [[email protected]] has left #mctxuwa_softdev []
+13:21 -!- jtanx [[email protected]] has joined #mctxuwa_softdev
+15:10 < jtanx> Eh, you know what I'll just stop the threads when you want to pause it
+15:10 < jtanx> instead of conditionals
+15:11 < jtanx> it's not like you're pausing the experiment that often
+15:18 < sam_moore> That's fine
+15:19 < sam_moore> The conditional approach is only really necessary if you're constantly pausing the threads
+15:19 < sam_moore> I used it for an nbody simulator, so the computation of force and position was split up between threads
+15:19 < sam_moore> It's really slow if you have to stop and then recreate the threads on every step
+15:22 < sam_moore> Although still actually faster than the single threaded program
+15:22 < sam_moore> Well, depending on how many objects you simulated
+15:23 < sam_moore> Anyway, just stop the threads, it's simpler to code and the performance effect in our case is probably negligable
+15:30 < jtanx> yeah
+15:30 < jtanx> say you had an actuator that was being controlled at that instant when an 'emergency stop' was issued
+15:31 < jtanx> since an 'emergency stop' is the same as just pausing (eg stopping the thread but keep DataFile open)
+15:31 < jtanx> you'd have to wait for that action to be completed before the 'emergency stop' would be propagated
+15:34 < jtanx> welp I guess that's why there's hardware safety interlocks
+15:38 < jtanx> Also, technically wouldn't it be possible to try to set the actuator value before the current value has been set
+15:38 < jtanx> Since there's no queue
+15:39 < jtanx> a->control could be overwritten by a new request as Actuator_SetValue operates
+16:12 < sam_moore> We want that right?
+16:13 < sam_moore> I'll look at it later if I get time
+16:14 < jtanx> I don't know if we want that or not
+16:15 < jtanx> wait want as in the current behaviour or the behaviour with a queue?
+16:16 < sam_moore> The current behaviour
+16:16 < sam_moore> I don't think you need a queue
+16:16 < sam_moore> You can extend the critical section in Actuator_Loop to stop the current control getting overwritten
+16:17 < sam_moore> Move the pthread_mutex_unlock on line 121 to below line 127 (Actuator_SetValue)
+16:17 < sam_moore> That way if Actuator_SetControl is called before the value has been successfully set, it will just wait
+16:17 < sam_moore> Mutexes actually implement a queue
+16:18 < sam_moore> If one thread has a lock on the mutex, subsequent threads that try to access the mutex will queue up; whenever the mutex is unlocked the next thread (if any) which was waiting will get it
+16:18 < jtanx> ok
+16:23 < jtanx> I'll leave it as is for now
+16:23 < sam_moore> Sure
+16:49 < sam_moore> PWM working
+16:49 < jtanx> nice
+16:50 < jtanx> I still don't really understand - did you compile the kernel from scratch
+16:50 < jtanx> or did you figure out how to use the install-me.sh script
+16:50 < sam_moore> I did, but I didn't need to modify it
+16:50 < jtanx> huh
+16:50 < jtanx> ok
+16:51 < sam_moore> http://www.eewiki.net/display/linuxonarm/BeagleBone+Black#BeagleBoneBlack-LinuxKernel
+16:52 < jtanx> so if we do this: http://www.eewiki.net/display/linuxonarm/BeagleBone+Black#BeagleBoneBlack-Networking:UsingasharedSDcardwithMultipleBeagleBone
+16:52 < jtanx> We should be able to just copy our image
+16:52 < jtanx> and stick it on the electronics' BBB
+16:53 < sam_moore> Sounds good
+16:53 < sam_moore> I'm glad that worked
+16:53 < jtanx> yeah
+16:54 < jtanx> I wonder if it also enabled the usb0 stuff (ethernet over usb)
+16:58 < sam_moore> PWM appears to have picosecond resolution? Or at least the arguments are in ps
+17:02 < jtanx> oO
+17:11 < sam_moore> ADC can sample at ~4KHz
+17:11 < sam_moore> But... that's using bash
+17:11 < sam_moore> It will probably be massively fast when done in C
+17:11 < jtanx> um
+17:11 < jtanx> is there any need to have it sample at a consistent rate
+17:11 < jtanx> as in, with threads there's no guarantee
+17:12 < jtanx> of a consistent sampling rate
+17:12 < sam_moore> Yes, you're right
+17:13 < sam_moore> I don't think we can achieve a consistent sampling rate, but I don't think it's critical that we do
+17:14 < sam_moore> As soon as we make our software run in an operating system with a kernel and other processes that can run as well, it gets pretty unfeasable to have a constant sample rate
+17:14 < sam_moore> We can have it constant to within an uncertainty I guess
+17:15 < jtanx> yeah, true
+17:18 < sam_moore> If you wanted a really high constant sample rate (say much faster than 1us which is probably the best case we could get) you'd have to use a more low level embedded device
+17:18 < sam_moore> Well I guess you could compile your own kernel for the BBB
+17:19 < sam_moore> But either way you'd have to physically run the webserver/GUI interface stuff on a seperate device
+17:19 < sam_moore> At this stage my feeling is what we have is good enough given the complexity of all the requirements we were given
+17:23 < jtanx> yeah
+17:25 < sam_moore> Hmm, I can set some GPIO pins to toggle whenever Sensor_Read is called and get an idea of sample rates and to what degree of accuracy we can quote the time stamps
+17:26 < sam_moore> I think I'll write some pin control code
+17:26 < sam_moore> I don't trust any of these custom libraries
+17:29 < jtanx> custom libraries?
+17:36 < sam_moore> Well they aren't really libraries
+17:36 < sam_moore> http://www.avrfreaks.net/wiki/index.php/Documentation:Linux/GPIO#Example_of_GPIO_access_from_within_a_C_program
+17:37 < sam_moore> Eg: That one has an fopen and fclose each time the value is changed
+17:38 < sam_moore> I could google until I find someone that has already written a C library, but chances are it will be slow or broken
+17:38 < sam_moore> Since I've worked out how to control the pins I may as well just write the C code to do it
+17:39 < jtanx> yep
+17:49 < sam_moore> I wonder if I can do this with a macro...
+18:30 < sam_moore> Ergh, screw that
+18:31 < sam_moore> Ok, I'm going to implement things like: GPIO/ADC/PWM_Export/Unexport to initialise or deinitialise all pins
+18:31 < jtanx> Ok
+18:31 < jtanx> too much effort with macros?
+18:31 < sam_moore> Yeah, 
+18:32 < sam_moore> I was thinking of having something like "GPIOX_Set()" instead of GPIO_Set(int x)"
+18:32 < sam_moore> But that's probably not as nice as I thought it was
+18:32 < sam_moore> Anyway, there's an enum in the header file that contains the id of all pins used
+18:32 < sam_moore> The implementation defines some structs that wrap around the file descriptors
+18:33 < sam_moore> But to use the module you just give it an ID as defined in the enums
+18:33 < jtanx> Makes sense
+18:33 < jtanx> designing the gui is actually not too bad
+18:33 < sam_moore> That's good
+18:34 < jtanx> looks ok in ie8 too
+18:34 < sam_moore> Nice
+18:35 < jtanx> gotta go, dinner
+18:35 < sam_moore> Ok
+18:35 < sam_moore> Hmm, it would be nice if C had value checking on enums
+18:35 < sam_moore> You can define a function that takes an enum type as an argument
+18:36 < sam_moore> But people can still just pass any old integer
+18:36 < sam_moore> As far as I know
+18:36 < sam_moore> eg: typedef enum {FIRST=1, SECOND=10, THIRD=100} EnumType
+18:36 < sam_moore> void Foo(EnumType e);
+18:37 < sam_moore> If you go Foo(2) it won't complain
+18:38 < sam_moore> Annoying
+18:38 < sam_moore> That seems like something the compiler would be able to pick up
+19:31 < sam_moore> Ergh, I'm getting too obsessive compulsive with this pin thing
+19:35 < sam_moore> It's annoying because ADC, GPIO and PWM are treated completely differently
+19:35 < sam_moore> You write one thing and it enables *all* the ADCs
+19:35 < sam_moore> You have to enable each GPIO pin individually
+19:36 < sam_moore> And to enable PWM pins you give a string (not just an integer)
+19:37 < sam_moore> Also the location of the pin files is not guaranteed (though it probably doesn't change for a given system configuration)
+19:39 < sam_moore> Ah, I found a way to enable pwm with /sys/class/ instead of that cape manager thing
+19:39 < sam_moore> I think I'll use that, since at least it's consistent with the GPIO stuff
+19:41 < sam_moore> Ooh!
+19:41 < sam_moore> http://beagleboard-gsoc13.blogspot.com.au/2013/07/sampling-analogue-signals-using-adc-on.html
+19:41 < sam_moore> Provides a driver for continuously sampling with the ADC
+19:41 < sam_moore> Oh wait
+19:41 < sam_moore> Crap in a bucket
+19:42 < sam_moore> Because we're using those multiplexers we can't do that
+19:42 < sam_moore> We have to set the multiplexer before each sample
+19:42 < sam_moore> Oh well, never mind
+19:44 < sam_moore> I suppose we could write our own kernel module :S
+19:45 < sam_moore> I think I understand this enough to talk to Adam next time he tries to talk about sample rate
+19:46 < sam_moore> 1. It's not actually constant, but we can probably have it constant to within a few us
+19:46 < sam_moore> 2. To make it constant would require writing a kernel module
+19:47 < sam_moore> Unless electronics stops being stingy and gets one amplifier per channel :P
+20:22 < jtanx> hehehe
+20:22 < jtanx> next week's adrian though
+20:22 < sam_moore> Ah
+20:23 < jtanx> grilling time
+20:23 < sam_moore> He'll probably ask us the same things :P
+20:23 < jtanx> yeah
+20:23 < jtanx> but man, so much stuff to go through just to get some readings from a few pins
+20:24 < jtanx> so good job with that :P
+20:54 < sam_moore> Thanks
+22:45 -!- jtanx [[email protected]] has quit ["ChatZilla 0.9.90.1 [Firefox 24.0/20130910160258]"]
+--- Day changed Sun Sep 22 2013
+00:51 < sam_moore> Hell yes
+00:51 < sam_moore> PWM controlled through web browser
+00:51 < sam_moore> GPIO controlled through web browser
index 3838876..1302544 100644 (file)
@@ -2,7 +2,7 @@
 CXX = gcc
 FLAGS = -std=c99 -Wall -pedantic -g -I/usr/include/opencv -I/usr/include/opencv2/highgui -L/usr/lib
 LIB = -lfcgi -lssl -lcrypto -lpthread -lm -lopencv_highgui -lopencv_core -lopencv_ml -lopencv_imgproc
-OBJ = log.o control.o data.o fastcgi.o main.o sensor.o actuator.o image.o
+OBJ = log.o control.o data.o fastcgi.o main.o sensor.o actuator.o image.o bbb_pin.o
 RM = rm -f
 
 BIN = server
@@ -10,12 +10,6 @@ BIN = server
 
 all : $(BIN) $(BIN2)
 
-stream : stream.c
-       $(CXX) $(FLAGS) -o stream stream.c $(LIB)
-
-intertest : interferometer.c
-       $(CXX) $(FLAGS) -o intertest interferometer.c $(LIB)
-
 
 $(BIN) : $(OBJ)
        $(CXX) $(FLAGS) -o $(BIN) $(OBJ) $(LIB)
index c71b05a..f5d7cd6 100644 (file)
@@ -5,13 +5,16 @@
 
 #include "actuator.h"
 #include "options.h"
+// Files containing GPIO and PWM definitions
+#include "bbb_pin.h"
+
 
 /** Array of Actuators (global to this file) initialised by Actuator_Init **/
 static Actuator g_actuators[NUMACTUATORS];
 
 /** Human readable names for the Actuators **/
 const char * g_actuator_names[NUMACTUATORS] = {        
-       "actuator_test0", "actuator_test1"
+       "actuator_test0", "gpio1_16", "EHRPWM0A_duty@60Hz"
 };
 
 /**
@@ -25,6 +28,11 @@ void Actuator_Init()
                Data_Init(&(g_actuators[i].data_file));
                pthread_mutex_init(&(g_actuators[i].mutex), NULL);
        }
+
+       // Initialise pins used
+       GPIO_Export(GPIO1_16);
+       PWM_Export(EHRPWM0A);
+       
 }
 
 /**
@@ -172,6 +180,7 @@ void Actuator_SetValue(Actuator * a, double value)
        {
                case ACTUATOR_TEST0: 
                        {
+                       // Onboard LEDs test actuator
                                FILE *led_handle = NULL;        //code reference: http://learnbuildshare.wordpress.com/2013/05/19/beaglebone-black-controlling-user-leds-using-c/
                                const char *led_format = "/sys/class/leds/beaglebone:green:usr%d/brightness";
                                char buf[50];
@@ -194,7 +203,15 @@ void Actuator_SetValue(Actuator * a, double value)
                        }
                        break;
                case ACTUATOR_TEST1:
+                       GPIO_Set(GPIO1_16, (bool)(value));
                        break;
+               case ACTUATOR_TEST2:
+               {
+                       // PWM analogue actuator (currently generates one PWM signal with first PWM module)
+                       static long freq = 16666666; // This is 60Hz
+                       PWM_Set(EHRPWM0A, true, freq, value * freq); // Set the duty cycle
+                       break;
+               }
        }
 
        Log(LOGDEBUG, "Actuator %s set to %f", g_actuator_names[a->id], value);
@@ -217,6 +234,7 @@ void Actuator_BeginResponse(FCGIContext * context, ActuatorId id, DataFormat for
                case JSON:
                        FCGI_BeginJSON(context, STATUS_OK);
                        FCGI_JSONLong("id", id);
+                       FCGI_JSONPair("name", g_actuator_names[id]);
                        break;
                default:
                        FCGI_PrintRaw("Content-type: text/plain\r\n\r\n");
index ee0ed32..48e0f29 100644 (file)
 //             Might be OK in C++ but not easy in C
 
 /** Number of actuators **/
-#define NUMACTUATORS 2
+#define NUMACTUATORS 3
 
 /** List of actuator ids (should be of size NUMACTUATORS) **/
 typedef enum
 {
        ACTUATOR_TEST0,
-       ACTUATOR_TEST1
+       ACTUATOR_TEST1,
+       ACTUATOR_TEST2
 } ActuatorId;
 
 /** Human readable names for the Actuators **/
diff --git a/server/bbb_pin.c b/server/bbb_pin.c
new file mode 100644 (file)
index 0000000..f8ba011
--- /dev/null
@@ -0,0 +1,326 @@
+/**
+ * @file bbb_pin.c
+ * @purpose Implementation of BBB pin control functions and structures
+ * THIS CODE IS NOT THREADSAFE
+ */
+
+#include "bbb_pin.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+/**
+ * Structure to represent a GPIO pin
+ * Note: Only accessable to this file; to use the functions pass a GPIOId
+ */
+typedef struct
+{
+       int fd_value;
+       int fd_direction;
+} GPIO_Pin;
+
+/**
+ * Structure to represent an ADC pin
+ * Note: Only accessable to this file; to use the functions pass a ADCId
+ */
+typedef struct
+{
+       FILE * file_value;
+} ADC_Pin;
+
+/**
+ * Structure to represent a PWM pin
+ * Note: Only accessable to this file; to use the functions pass a PWMId
+ */
+typedef struct
+{
+       int fd_run;
+       FILE * file_duty;
+       FILE * file_period;
+       int fd_polarity;
+} PWM_Pin;
+
+/** Array of GPIO pins **/
+static GPIO_Pin g_gpio[GPIO_NUM_PINS] = {{0}};
+/** Array of ADC pins **/
+static ADC_Pin g_adc[ADC_NUM_PINS] = {{0}};
+/** Array of PWM pins **/
+static PWM_Pin g_pwm[PWM_NUM_PINS] = {{0}};
+
+static char g_buffer[BUFSIZ] = "";
+
+
+
+
+/**
+ * Export a GPIO pin and open the file descriptors
+ */
+void GPIO_Export(int pin)
+{
+       if (pin < 0 || pin > GPIO_NUM_PINS)
+               Fatal("Invalid pin number %d", pin);
+
+       
+
+       // Export the pin
+       sprintf(g_buffer, "%s/export", GPIO_DEVICE_PATH);
+       FILE * export = fopen(g_buffer, "w");
+       if (export == NULL)
+               Fatal("Couldn't open %s to export GPIO pin %d - %s", g_buffer, pin, strerror(errno));
+
+       fprintf(export, "%d", pin);     
+       fclose(export);
+       
+       // Setup direction file descriptor
+       sprintf(g_buffer, "%s/gpio%d/direction", GPIO_DEVICE_PATH, pin);
+       g_gpio[pin].fd_direction = open(g_buffer, O_RDWR);
+       if (g_gpio[pin].fd_direction < 0)
+               Fatal("Couldn't open %s for GPIO pin %d - %s", g_buffer, pin, strerror(errno));
+
+
+       // Setup value file descriptor
+       sprintf(g_buffer, "%s/gpio%d/value", GPIO_DEVICE_PATH, pin);
+       g_gpio[pin].fd_value = open(g_buffer, O_RDWR);
+       if (g_gpio[pin].fd_value < 0)
+               Fatal("Couldn't open %s for GPIO pin %d - %s", g_buffer, pin, strerror(errno));
+}
+
+/**
+ * Unexport a GPIO pin and close its' file descriptors
+ */
+void GPIO_Unexport(int pin)
+{
+
+       if (pin < 0 || pin > GPIO_NUM_PINS)
+               Fatal("Invalid pin number %d", pin);
+
+       // Close file descriptors
+       close(g_gpio[pin].fd_value);
+       close(g_gpio[pin].fd_direction);
+
+       // Unexport the pin
+
+       if (g_buffer[0] == '\0')
+               sprintf(g_buffer, "%s/unexport", GPIO_DEVICE_PATH);     
+       FILE * export = fopen(g_buffer, "w");
+       if (export == NULL)
+               Fatal("Couldn't open %s to export GPIO pin %d - %s", g_buffer, pin, strerror(errno));
+
+       fprintf(export, "%d", pin);     
+       fclose(export);
+}
+
+
+
+
+/**
+ * Export all PWM pins and open file descriptors
+ * @param pin - The pin number
+ */
+void PWM_Export(int pin)
+{
+       if (pin < 0 || pin > PWM_NUM_PINS)
+               Fatal("Invalid pin number %d", pin);
+       
+       // Export the pin
+       sprintf(g_buffer, "%s/export", PWM_DEVICE_PATH);
+       FILE * export = fopen(g_buffer, "w");
+       if (export == NULL)
+               Fatal("Couldn't open %s to export PWM pin %d - %s", g_buffer, pin, strerror(errno));
+       
+       fprintf(export, "%d", pin);
+       fclose(export);
+
+       // Open file descriptors
+       sprintf(g_buffer, "%s/pwm%d/run", PWM_DEVICE_PATH, pin);
+       g_pwm[pin].fd_run = open(g_buffer, O_WRONLY);
+       if (g_pwm[pin].fd_run < 0)
+               Fatal("Couldn't open %s for PWM pin %d - %s", g_buffer, pin, strerror(errno));
+
+       sprintf(g_buffer, "%s/pwm%d/polarity",PWM_DEVICE_PATH, pin);
+       g_pwm[pin].fd_polarity = open(g_buffer, O_WRONLY);
+       if (g_pwm[pin].fd_polarity < 0)
+               Fatal("Couldn't open %s for PWM pin %d - %s", g_buffer, pin, strerror(errno));
+
+       sprintf(g_buffer, "%s/pwm%d/period_ns",PWM_DEVICE_PATH, pin);
+       g_pwm[pin].file_period = fopen(g_buffer, "w");
+       if (g_pwm[pin].file_period == NULL)
+               Fatal("Couldn't open %s for PWM pin %d - %s", g_buffer, pin, strerror(errno));
+
+       sprintf(g_buffer, "%s/pwm%d/duty_ns",PWM_DEVICE_PATH, pin);
+       g_pwm[pin].file_duty = fopen(g_buffer, "w");
+       if (g_pwm[pin].file_duty == NULL)
+               Fatal("Couldn't open %s for PWM pin %d - %s", g_buffer, pin, strerror(errno));
+
+       // Don't buffer the streams
+       setbuf(g_pwm[pin].file_period, NULL);
+       setbuf(g_pwm[pin].file_duty, NULL);
+
+       
+}
+
+/**
+ * Unexport a PWM pin and close its file descriptors
+ * @param pin - The pin number
+ */
+void PWM_Unexport(int pin)
+{
+       if (pin < 0 || pin > PWM_NUM_PINS)
+               Fatal("Invalid pin number %d", pin);
+
+       // Close the file descriptors
+       close(g_pwm[pin].fd_polarity);
+       close(g_pwm[pin].fd_run);
+       fclose(g_pwm[pin].file_period);
+       fclose(g_pwm[pin].file_duty);
+
+       //Unexport the pin
+       sprintf(g_buffer, "%s/unexport", PWM_DEVICE_PATH);
+       FILE * export = fopen(g_buffer, "w");
+       if (export == NULL)
+               Fatal("Couldn't open %s to unexport PWM pin %d - %s", g_buffer, pin, strerror(errno));
+       
+       fprintf(export, "%d", pin);
+       fclose(export);
+
+
+}
+
+/**
+ * Export ADC pins; http://beaglebone.cameon.net/home/reading-the-analog-inputs-adc
+ * Can't use sysfs like GPIO or PWM pins
+ * Bloody annoying how inconsistent stuff is on the Beaglebone
+ */
+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)
+                       Fatal("Couldn't open ADC %d device file %s - %s", i, g_buffer, strerror(errno));
+
+               setbuf(g_adc[i].file_value, NULL);
+
+       }
+}
+
+/**
+ * Unexport ADC pins
+ */
+void ADC_Unexport()
+{
+       for (int i = 0; i < ADC_NUM_PINS; ++i)
+               fclose(g_adc[i].file_value);
+}
+
+/**
+ * Set a GPIO pin
+ * @param pin - The pin to set. MUST have been exported before calling this function.
+ */
+void GPIO_Set(int pin, bool value)
+{
+       if (pwrite(g_gpio[pin].fd_direction, "out", 3*sizeof(char), 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)
+               Fatal("Couldn't read GPIO %d value - %s", pin, strerror(errno));
+
+}
+
+/** 
+ * Read from a GPIO Pin
+ * @param pin - The pin to read
+ */
+bool GPIO_Read(int pin)
+{
+       if (pwrite(g_gpio[pin].fd_direction, "in", 2*sizeof(char), 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)
+               Fatal("Couldn't read GPIO %d value - %s", pin, strerror(errno));
+
+       return (c == '1');
+
+}
+
+/**
+ * Activate a PWM pin
+ * @param pin - The pin to activate
+ * @param polarity - if true, pin is active high, else active low
+ * @param period - The period in ns
+ * @param duty - The time the pin is active in ns
+ */
+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)
+               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)
+               Fatal("Couldn't set PWM %d polarity - %s", pin, strerror(errno));
+
+       
+       rewind(g_pwm[pin].file_period); 
+       rewind(g_pwm[pin].file_duty);
+
+       if (fprintf(g_pwm[pin].file_duty, "%lu", duty) == 0)
+               Fatal("Couldn't set duty cycle for PWM %d - %s", pin, strerror(errno));
+
+       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)
+               Fatal("Couldn't start PWM %d - %s", pin, strerror(errno));
+
+}
+
+/**
+ * Deactivate a PWM pin
+ * @param pin - The pin to turn off
+ */
+void PWM_Stop(int pin)
+{
+       if (pwrite(g_pwm[pin].fd_run, "0", 1*sizeof(char), 0) != 1)
+               Fatal("Couldn't stop PWM %d - %s", pin, strerror(errno));
+
+}
+
+/**
+ * Read an ADC value
+ * @param id - The ID of the ADC pin to read
+ * @returns - The reading of the ADC channel
+ */
+long 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)
+       {
+               if (adc_val[i] == '\n')
+                       adc_val[i] = '\0';
+       }
+
+       char * end;
+       long val = strtol(adc_val, &end, 10);
+       if (*end != '\0')
+       {
+               Log(LOGERR, "Reading ADC%d gives %s - invalid!", id, adc_val);
+       }
+       //Log(LOGDEBUG, "Returns %lu", val);
+       return val;
+}
diff --git a/server/bbb_pin.h b/server/bbb_pin.h
new file mode 100644 (file)
index 0000000..472a917
--- /dev/null
@@ -0,0 +1,36 @@
+/**
+ * @file bbb_pin.h
+ * @brief Definition of functions for controlling pins on the Beaglebone Black
+ */
+
+#ifndef _BBB_PIN_H
+#define _BBB_PIN_H
+
+#include "common.h"
+
+#include "bbb_pin_defines.h"
+
+// Initialise / Deinitialise functions
+extern void GPIO_Export(int pin);
+extern void GPIO_Unexport(int pin);
+
+extern void PWM_Export(int pin);
+extern void PWM_Unexport(int pin);
+
+extern void ADC_Export();
+extern void ADC_Unexport();
+
+// Pin reading/setting functions
+extern bool GPIO_Read(int pin);
+extern void GPIO_Set(int pin, bool value);
+
+extern long 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);
+
+
+
+#endif //_BBB_PIN_H
+
+//EOF
diff --git a/server/bbb_pin_defines.h b/server/bbb_pin_defines.h
new file mode 100644 (file)
index 0000000..dba2d5c
--- /dev/null
@@ -0,0 +1,154 @@
+/**
+ * @file bbb_pin_defines.h
+ * @brief Defines pins on Beaglebone Black
+ */
+
+#ifndef _BBB_PIN_DEFINES_H
+#define _BBB_PIN_DEFINES_H
+
+/** GPIO0 defines **/
+
+#define GPIO0_1 1
+#define GPIO0_2 2
+//#define GPIO0_3 3 // Used for PWM
+//#define GPIO0_4 4 // Used for PWM
+#define GPIO0_5 5
+#define GPIO0_6 6
+#define GPIO0_7 7
+#define GPIO0_8 8
+#define GPIO0_9 9
+#define GPIO0_10 10
+#define GPIO0_11 11
+#define GPIO0_12 12
+#define GPIO0_13 13
+#define GPIO0_14 14
+#define GPIO0_15 15
+#define GPIO0_16 16
+#define GPIO0_17 17
+#define GPIO0_18 18
+#define GPIO0_19 19
+#define GPIO0_20 20
+#define GPIO0_21 21
+#define GPIO0_22 22
+#define GPIO0_23 23
+#define GPIO0_24 24
+#define GPIO0_25 25
+#define GPIO0_26 26
+#define GPIO0_27 27
+#define GPIO0_28 28
+#define GPIO0_29 29
+#define GPIO0_30 30
+#define GPIO0_31 31
+#define GPIO0_32 32
+
+/** GPIO1 defines **/
+
+#define GPIO1_1 33
+#define GPIO1_2 34
+#define GPIO1_3 35
+#define GPIO1_4 36
+#define GPIO1_5 37
+#define GPIO1_6 38
+#define GPIO1_7 39
+#define GPIO1_8 40
+#define GPIO1_9 41
+#define GPIO1_10 42
+#define GPIO1_11 43
+#define GPIO1_12 44
+#define GPIO1_13 45
+#define GPIO1_14 46
+#define GPIO1_15 47
+#define GPIO1_16 48
+#define GPIO1_17 49
+#define GPIO1_18 50
+#define GPIO1_19 51
+#define GPIO1_20 52
+#define GPIO1_21 53
+#define GPIO1_22 54
+#define GPIO1_23 55
+#define GPIO1_24 56
+#define GPIO1_25 57
+#define GPIO1_26 58
+#define GPIO1_27 59
+#define GPIO1_28 60
+#define GPIO1_29 61
+#define GPIO1_30 62
+#define GPIO1_31 63
+#define GPIO1_32 64
+
+/** GPIO2 defines **/
+
+#define GPIO2_1 65
+#define GPIO2_2 66
+#define GPIO2_3 67
+#define GPIO2_4 68
+#define GPIO2_5 69
+#define GPIO2_6 70
+#define GPIO2_7 71
+#define GPIO2_8 72
+#define GPIO2_9 73
+#define GPIO2_10 74
+#define GPIO2_11 75
+#define GPIO2_12 76
+#define GPIO2_13 77
+#define GPIO2_14 78
+#define GPIO2_15 79
+#define GPIO2_16 80
+#define GPIO2_17 81
+#define GPIO2_18 82
+#define GPIO2_19 83
+#define GPIO2_20 84
+#define GPIO2_21 85
+#define GPIO2_22 86
+#define GPIO2_23 87
+#define GPIO2_24 88
+#define GPIO2_25 89
+#define GPIO2_26 90
+#define GPIO2_27 91
+#define GPIO2_28 92
+#define GPIO2_29 93
+#define GPIO2_30 94
+#define GPIO2_31 95
+#define GPIO2_32 96
+
+/** Number of GPIO pins **/
+#define GPIO_NUM_PINS 97
+
+/** Export path **/
+#define GPIO_DEVICE_PATH "/sys/class/gpio"
+
+#define ADC_BITS 12
+#define ADC_DIGITS 5
+#define ADC0 0
+#define ADC1 1
+#define ADC2 2
+#define ADC3 3
+#define ADC4 4
+#define ADC5 5
+#define ADC6 6
+#define ADC7 7
+
+/** Number of ADC pins **/
+#define ADC_NUM_PINS 8
+
+/** Path to export ADCs with**/
+#define ADC_EXPORT_PATH "/sys/devices/bone_capemgr.9/slots"
+/** Path at which ADCs appear **/
+#define ADC_DEVICE_PATH "/sys/devices/ocp.3/helper.16"
+
+/** PWM defines **/
+#define EHRPWM0A 0
+#define EHRPWM0B 1
+// No other PWM pins work!
+
+/** Number of PWM pins **/
+#define PWM_NUM_PINS 2
+
+/** Path to PWM sysfs **/
+#define PWM_DEVICE_PATH "/sys/class/pwm"
+
+
+
+#endif //_BBB_PIN_DEFINES_H
+
+
index a648ae8..67f7de3 100644 (file)
@@ -447,15 +447,17 @@ void * FCGI_RequestLoop (void *data)
 {
        FCGIContext context = {0};
        
-       Log(LOGDEBUG, "First request...");
+       Log(LOGDEBUG, "Start loop");
        while (FCGI_Accept() >= 0) {
-               Log(LOGDEBUG, "Got request #%d", context.response_number);
+               
                ModuleHandler module_handler = NULL;
                char module[BUFSIZ], params[BUFSIZ];
                
                //strncpy doesn't zero-truncate properly
                snprintf(module, BUFSIZ, "%s", getenv("DOCUMENT_URI_LOCAL"));
                snprintf(params, BUFSIZ, "%s", getenv("QUERY_STRING"));
+
+               Log(LOGDEBUG, "Got request #%d - Module %s, params %s", context.response_number, module, params);
                
                //Remove trailing slashes (if present) from module query
                size_t lastchar = strlen(module) - 1;
@@ -489,7 +491,7 @@ void * FCGI_RequestLoop (void *data)
                }
                context.response_number++;
 
-               Log(LOGDEBUG, "Waiting for request #%d", context.response_number);
+               
        }
 
        Log(LOGDEBUG, "Thread exiting.");
index d41021f..c23d158 100644 (file)
@@ -22,10 +22,12 @@ static const char * unspecified_funct = "???";
        If level is higher (less urgent) than the program's verbosity (see options.h) no message will be printed
  * @param funct - String indicating the function name from which this function was called.
        If this is NULL, Log will show the unspecified_funct string instead
+ * @param file - Source file containing the function
+ * @param line - Line in the source file at which Log is called
  * @param fmt - A format string
  * @param ... - Arguments to be printed according to the format string
  */
-void LogEx(int level, const char * funct, ...)
+void LogEx(int level, const char * funct, const char * file, int line, ...)
 {
        //Todo: consider setlogmask(3) to filter messages
        const char *fmt;
@@ -36,7 +38,7 @@ void LogEx(int level, const char * funct, ...)
        if (level > g_options.verbosity)
                return;
 
-       va_start(va, funct);
+       va_start(va, line);
        fmt = va_arg(va, const char*);
        
        if (fmt == NULL) // sanity check
@@ -74,22 +76,24 @@ void LogEx(int level, const char * funct, ...)
                        break;
        }
 
-       syslog(level, "%s: %s - %s", severity, funct, buffer);
+       syslog(level, "%s: %s (%s:%d) - %s", severity, funct, file, line, buffer);
 }
 
 /**
  * Handle a Fatal error in the program by printing a message and exiting the program
  *     CALLING THIS FUNCTION WILL CAUSE THE PROGAM TO EXIT
  * @param funct - Name of the calling function
+ * @param file - Name of the source file containing the calling function
+ * @param line - Line in the source file at which Fatal is called
  * @param fmt - A format string
  * @param ... - Arguments to be printed according to the format string
  */
-void FatalEx(const char * funct, ...)
+void FatalEx(const char * funct, const char * file, int line, ...)
 {
        const char *fmt;
        char buffer[BUFSIZ];
        va_list va;
-       va_start(va, funct);
+       va_start(va, line);
        fmt = va_arg(va, const char*);
        
        if (fmt == NULL)
@@ -106,7 +110,7 @@ void FatalEx(const char * funct, ...)
        if (funct == NULL)
                funct = unspecified_funct;
 
-       syslog(LOG_CRIT, "FATAL: %s - %s", funct, buffer);
+       syslog(LOG_CRIT, "FATAL: %s (%s:%d) - %s", funct, file, line, buffer);
        exit(EXIT_FAILURE);
 }
 
index eec5e53..fd98190 100644 (file)
@@ -7,14 +7,14 @@
 #define _LOG_H
 
 //To get around a 'pedantic' C99 rule that you must have at least 1 variadic arg, combine fmt into that.
-#define Log(level, ...) LogEx(level, __func__, __VA_ARGS__)
-#define Fatal(...) FatalEx(__func__, __VA_ARGS__)
+#define Log(level, ...) LogEx(level, __func__, __FILE__, __LINE__, __VA_ARGS__)
+#define Fatal(...) FatalEx(__func__, __FILE__, __LINE__, __VA_ARGS__)
 
 // An enum to make the severity of log messages human readable in code
 enum {LOGERR=0, LOGWARN=1, LOGNOTE=2, LOGINFO=3,LOGDEBUG=4};
 
-extern void LogEx(int level, const char * funct, ...); // General function for printing log messages to stderr
-extern void FatalEx(const char * funct, ...); // Function that deals with a fatal error (prints a message, then exits the program).
+extern void LogEx(int level, const char * funct, const char * file, int line,  ...); // General function for printing log messages to stderr
+extern void FatalEx(const char * funct, const char * file, int line, ...); // Function that deals with a fatal error (prints a message, then exits the program).
 
 #endif //_LOG_H
 
index 64c7aa9..e429958 100644 (file)
@@ -7,6 +7,7 @@
 #include "common.h"
 #include "sensor.h"
 #include "options.h"
+#include "bbb_pin.h"
 #include <math.h>
 
 /** Array of sensors, initialised by Sensor_Init **/
@@ -17,17 +18,20 @@ const SensorThreshold thresholds[NUMSENSORS]= {
        //Max Safety, Min safety, Max warning, Min warning
        {1,-1,1,-1},            // ANALOG_TEST0
        {500,0,499,0},          // ANALOG_TEST1
+       {5000,0,5000,0},                // ANALOG_REALTEST
        {5,-5,4,-4},            // ANALOG_FAIL0
        {1,0,1,0},                      // DIGITAL_TEST0
        {1,0,1,0},                      // DIGITAL_TEST1
+       {1,0,1,0},                      // DIGITAL_REALTEST
        {1,0,1,0}                       // DIGITAL_FAIL0
 };
 
 /** Human readable names for the sensors **/
 const char * g_sensor_names[NUMSENSORS] = {    
        "analog_test0", "analog_test1", 
-       "analog_fail0", "digital_test0", 
-       "digital_test1", "digital_fail0"
+       "analog_realtest", "analog_fail0",
+       "digital_test0", "digital_test1", 
+       "digital_realtest", "digital_fail0"
 };
 
 /**
@@ -40,6 +44,14 @@ void Sensor_Init()
                g_sensors[i].id = i;
                Data_Init(&(g_sensors[i].data_file));
        }
+
+       // Get the ADCs
+       ADC_Export();
+
+       // GPIO1_28 used as a pulse for sampling
+       GPIO_Export(GPIO1_28);
+       // GPIO0_30 toggled during sampling
+       GPIO_Export(GPIO0_30);
 }
 
 /**
@@ -157,12 +169,37 @@ bool Sensor_Read(Sensor * s, DataPoint * d)
        gettimeofday(&t, NULL);
        d->time_stamp = TIMEVAL_DIFF(t, *Control_GetStartTime());
 
+       static bool result = true;
+       
+       
        // Read value based on Sensor Id
        switch (s->id)
        {
+               case ANALOG_REALTEST:
+               {
+                       static bool set = false;
+                       
+                       GPIO_Set(GPIO0_30, true);
+                       d->value = (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;
+                       GPIO_Set(GPIO1_28, set);
+                       
+                       break;
+               }
+               
+               default:
+                       d->value = rand() % 2;
+                       usleep(1000000);
+                       break;
+               
+
                case ANALOG_TEST0:
+               {
                        d->value = (double)(rand() % 100) / 100;
                        break;
+               }
                case ANALOG_TEST1:
                {
                        static int count = 0;
@@ -170,33 +207,43 @@ bool Sensor_Read(Sensor * s, DataPoint * d)
                        d->value = count++;
                        break;
                }
+
                case ANALOG_FAIL0:
-                       d->value = (double)(rand() % 6) * -( rand() % 2) / ( rand() % 100 + 1);
+                       d->value = 0;
+                       //d->value = (double)(rand() % 6) * -( rand() % 2) / ( rand() % 100 + 1);
                        //Gives a value between -5 and 5
                        break;
                case DIGITAL_TEST0:
                        d->value = t.tv_sec % 2;
+
                        break;
                case DIGITAL_TEST1:
                        d->value = (t.tv_sec+1)%2;
                        break;
+               case DIGITAL_REALTEST:
+               {
+               // Can pass pin as argument, just using 20 as an example here
+               // Although since pins will be fixed, can just define it here if we need to
+                       //d->value = pinRead(20);       //Pin 20 on the Beaglebone
+                       break;
+               }
                case DIGITAL_FAIL0:
                        if( rand() % 100 > 98)
                                d->value = 2;
                        d->value = rand() % 2; 
                        //Gives 0 or 1 or a 2 every 1/100 times
                        break;
-               default:
-                       Fatal("Unknown sensor id: %d", s->id);
-                       break;
+               //default:
+               //      Fatal("Unknown sensor id: %d", s->id);
+               //      break;
        }       
-       usleep(100000); // simulate delay in sensor polling
+       
 
        // Perform sanity check based on Sensor's ID and the DataPoint
        Sensor_CheckData(s->id, d->value);
 
        // Update latest DataPoint if necessary
-       bool result = (d->value != s->newest_data.value);
+       
        if (result)
        {
                s->newest_data.time_stamp = d->time_stamp;
@@ -270,6 +317,7 @@ void Sensor_BeginResponse(FCGIContext * context, SensorId id, DataFormat format)
                case JSON:
                        FCGI_BeginJSON(context, STATUS_OK);
                        FCGI_JSONLong("id", id);
+                       FCGI_JSONPair("name", g_sensor_names[id]);
                        break;
                default:
                        FCGI_PrintRaw("Content-type: text/plain\r\n\r\n");
index 6c7abaa..182d8ae 100644 (file)
@@ -9,16 +9,18 @@
 #include "data.h"
 
 /** Number of sensors **/
-#define NUMSENSORS 
+#define NUMSENSORS 8
 
 /** Sensor ids - there should be correspondence with the names in g_sensor_names **/
 typedef enum SensorId 
 {
        ANALOG_TEST0,
        ANALOG_TEST1,
+       ANALOG_REALTEST,
        ANALOG_FAIL0,
        DIGITAL_TEST0,
        DIGITAL_TEST1,
+       DIGITAL_REALTEST,
        DIGITAL_FAIL0
 } SensorId;
 
index da4e0d0..7d7a8fe 100644 (file)
@@ -8,7 +8,7 @@ $(document).ready(function()
 {
 
        g_sensors = []
-       g_numSensors = 2
+       g_numSensors = 1
        g_storeTime = []
        g_key = null
 
@@ -44,7 +44,7 @@ $(document).ready(function()
        $.fn.updateSensor = function(json)
        {
                //console.log(json.data)
-               var sensor = g_sensors[json.id]
+               var sensor = g_sensors[0]
                var most_recent = null
                if (sensor.length > 0)
                        most_recent = sensor[sensor.length-1][0]
@@ -62,7 +62,7 @@ $(document).ready(function()
                
                //console.log("Plot:")
                //console.log(g_sensors[json.id])
-               $.plot("#sensor"+String(json.id)+"_plot", [g_sensors[json.id]])
+               $.plot("#sensor"+String(0)+"_plot", [g_sensors[0]])
                $.ajax({url : "/api/sensors", data : {id : json.id}, success : function(data) {$(this).updateSensor(data);}});
                
                //
@@ -127,7 +127,7 @@ $(document).ready(function()
 
        for (var i = 0; i < g_numSensors; ++i)
        {
-       //      $.ajax({url : "/api/sensors", data : {id : i}, success : function(data) {$(this).updateSensor(data);}})
+         $.ajax({url : "/api/sensors", data : {id : 2}, success : function(data) {$(this).updateSensor(data);}})
 
        }
 });

UCC git Repository :: git.ucc.asn.au