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)
1  2 
server/actuator.c
server/actuator.h
server/fastcgi.c
server/sensor.c
server/sensor.h

diff --combined server/actuator.c
@@@ -5,13 -5,16 +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 +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);
+       
  }
  
  /**
@@@ -44,6 -52,7 +52,6 @@@ void Actuator_SetMode(Actuator * a, Con
                        {
                                char filename[BUFSIZ];
                                const char *experiment_name = (const char*) arg;
 -                              int ret;
  
                                if (snprintf(filename, BUFSIZ, "%s_a%d", experiment_name, a->id) >= BUFSIZ)
                                {
                                Log(LOGDEBUG, "Actuator %d with DataFile \"%s\"", a->id, filename);
                                // Open DataFile
                                Data_Open(&(a->data_file), filename);
 -
 +                      } 
 +              case CONTROL_RESUME:  //Case fallthrough; no break before
 +                      {
 +                              int ret;
                                a->activated = true; // Don't forget this
 -                              a->allow_actuation = true;
 -
                                a->control_changed = false;
  
 -                              // Create the thread
                                ret = pthread_create(&(a->thread), NULL, Actuator_Loop, (void*)(a));
                                if (ret != 0)
                                {
                                        Fatal("Failed to create Actuator_Loop for Actuator %d", a->id);
                                }
 +
 +                              Log(LOGDEBUG, "Resuming actuator %d", a->id);
                        }
                break;
  
                case CONTROL_EMERGENCY: //TODO add proper case for emergency
                case CONTROL_PAUSE:
 -                      a->allow_actuation = false;
 +                      a->activated = false;
 +                      Actuator_SetControl(a, NULL);
 +                      pthread_join(a->thread, NULL); // Wait for thread to exit
 +
 +                      Log(LOGDEBUG, "Paused actuator %d", a->id);
                break;
 -              case CONTROL_RESUME:
 -                      a->allow_actuation = true;
 +
                break;
                case CONTROL_STOP:
 -                      a->allow_actuation = false;
 -                      a->activated = false;
 -                      Actuator_SetControl(a, NULL);
 -                      pthread_join(a->thread, NULL); // Wait for thread to exit       
 +                      if (a->activated) //May have been paused before
 +                      {
 +                              a->activated = false;
 +                              Actuator_SetControl(a, NULL);
 +                              pthread_join(a->thread, NULL); // Wait for thread to exit       
 +                      }
                        Data_Close(&(a->data_file)); // Close DataFile
 +                      
 +                      Log(LOGDEBUG, "Stopped actuator %d", a->id);
                break;
                default:
                        Fatal("Unknown control mode: %d", mode);
@@@ -129,6 -129,8 +137,6 @@@ void * Actuator_Loop(void * arg
                pthread_mutex_unlock(&(a->mutex));
                if (!a->activated)
                        break;
 -              else if (!a->allow_actuation)
 -                      continue;
  
                Actuator_SetValue(a, a->control.value);
        }
@@@ -172,6 -174,7 +180,7 @@@ void Actuator_SetValue(Actuator * a, do
        {
                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];
                        }
                        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 -228,7 +234,7 @@@ void Actuator_BeginResponse(FCGIContex
                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");
@@@ -244,6 -256,8 +262,6 @@@ void Actuator_EndResponse(FCGIContext 
  }
  
  
 -
 -
  /**
   * Handle a request for an Actuator
   * @param context - FCGI context
diff --combined server/actuator.h
  //            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 **/
@@@ -52,6 -53,8 +53,6 @@@ typedef struc
        pthread_cond_t cond;
        /** Indicates whether the Actuator is running **/
        bool activated;
 -      /** Indicates whether the Actuator can be actuated or not **/
 -      bool allow_actuation;
  
  } Actuator;
  
diff --combined server/fastcgi.c
@@@ -294,7 -294,6 +294,7 @@@ void FCGI_BeginJSON(FCGIContext *contex
        FCGI_JSONDouble("start_time", TIMEVAL_TO_DOUBLE(g_options.start_time));
        FCGI_JSONDouble("current_time", TIMEVAL_TO_DOUBLE(now));
        FCGI_JSONDouble("running_time", TIMEVAL_DIFF(now, g_options.start_time));
 +      FCGI_JSONPair("control_state", Control_GetModeName());
  }
  
  /**
@@@ -447,15 -446,17 +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;
                }
                context.response_number++;
  
-               Log(LOGDEBUG, "Waiting for request #%d", context.response_number);
+               
        }
  
        Log(LOGDEBUG, "Thread exiting.");
diff --combined server/sensor.c
@@@ -7,6 -7,7 +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 +18,20 @@@ const SensorThreshold thresholds[NUMSEN
        //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"
  };
  
  /**
@@@ -39,7 -43,16 +43,15 @@@ void Sensor_Init(
        {
                g_sensors[i].id = i;
                Data_Init(&(g_sensors[i].data_file));
 -              g_sensors[i].record_data = false;       
        }
+       // 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);
  }
  
  /**
@@@ -60,6 -73,7 +72,6 @@@ void Sensor_SetMode(Sensor * s, Control
                                // Set filename
                                char filename[BUFSIZ];
                                const char *experiment_name = (const char*) arg;
 -                              int ret;
  
                                if (snprintf(filename, BUFSIZ, "%s_s%d", experiment_name, s->id) >= BUFSIZ)
                                {
                                Log(LOGDEBUG, "Sensor %d with DataFile \"%s\"", s->id, filename);
                                // Open DataFile
                                Data_Open(&(s->data_file), filename);
 -
 -                              s->activated = true;
 -                              s->record_data = true; // Don't forget this!
 +                      }
 +              case CONTROL_RESUME: //Case fallthrough, no break before
 +                      {
 +                              int ret;
 +                              s->activated = true; // Don't forget this!
  
                                // Create the thread
                                ret = pthread_create(&(s->thread), NULL, Sensor_Loop, (void*)(s));
                                {
                                        Fatal("Failed to create Sensor_Loop for Sensor %d", s->id);
                                }
 +
 +                              Log(LOGDEBUG, "Resuming sensor %d", s->id);
                        }
 -                      break;
 +              break;
 +
                case CONTROL_EMERGENCY:
                case CONTROL_PAUSE:
 -                      s->record_data = false;
 -              break;
 -              case CONTROL_RESUME:
 -                      s->record_data = true;
 -              break;
 -              case CONTROL_STOP:
                        s->activated = false;
 -                      s->record_data = false;
                        pthread_join(s->thread, NULL);
 +                      Log(LOGDEBUG, "Paused sensor %d", s->id);
 +              break;
 +              
 +              case CONTROL_STOP:
 +                      if (s->activated) //May have been paused before
 +                      {
 +                              s->activated = false;
 +                              pthread_join(s->thread, NULL);
 +                      }
  
                        Data_Close(&(s->data_file)); // Close DataFile
                        s->newest_data.time_stamp = 0;
                        s->newest_data.value = 0;
 +                      Log(LOGDEBUG, "Stopped sensor %d", s->id);
                break;
                default:
                        Fatal("Unknown control mode: %d", mode);
@@@ -134,7 -140,6 +146,7 @@@ void Sensor_CheckData(SensorId id, doub
        {
                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);
                //new function that stops actuators?
 +              //Control_SetMode(CONTROL_EMERGENCY, NULL)
        }
        else if( value > thresholds[id].max_warn || value < thresholds[id].min_warn)
        {
@@@ -157,12 -162,37 +169,37 @@@ bool Sensor_Read(Sensor * s, DataPoint 
        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;
                        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;
@@@ -218,12 -258,20 +265,12 @@@ void * Sensor_Loop(void * arg
        // Until the sensor is stopped, record data points
        while (s->activated)
        {
 -              if (s->record_data)
 -              {
 -                      DataPoint d;
 -                      //Log(LOGDEBUG, "Sensor %d reads data [%f,%f]", s->id, d.time_stamp, d.value);
 -                      if (Sensor_Read(s, &d)) // If new DataPoint is read:
 -                      {
 -                              //Log(LOGDEBUG, "Sensor %d saves data [%f,%f]", s->id, d.time_stamp, d.value);
 -                              Data_Save(&(s->data_file), &d, 1); // Record it
 -                      }
 -              }
 -              else
 +              DataPoint d;
 +              //Log(LOGDEBUG, "Sensor %d reads data [%f,%f]", s->id, d.time_stamp, d.value);
 +              if (Sensor_Read(s, &d)) // If new DataPoint is read:
                {
 -                      //Do something? wait?
 -                      usleep(100000);
 +                      //Log(LOGDEBUG, "Sensor %d saves data [%f,%f]", s->id, d.time_stamp, d.value);
 +                      Data_Save(&(s->data_file), &d, 1); // Record it
                }
        }
        
@@@ -270,6 -318,7 +317,7 @@@ void Sensor_BeginResponse(FCGIContext 
                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");
diff --combined server/sensor.h
@@@ -9,16 -9,18 +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;
  
@@@ -32,8 -34,10 +34,8 @@@ typedef struc
        SensorId id;
        /** DataFile to store sensor values in **/
        DataFile data_file;
 -      /** Indicates whether the Sensor is not stopped **/
 +      /** Indicates whether the Sensor is active or not **/
        bool activated;
 -      /** Indicates whether the Sensor should record data **/
 -      bool record_data;
        /** Thread the Sensor is running in **/
        pthread_t thread;
        /** Most recently recorded data **/

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