From: Jeremy Tan Date: Sun, 22 Sep 2013 00:43:17 +0000 (+0800) Subject: Merge branch 'master' of https://github.com/szmoore/MCTX3420.git X-Git-Url: https://git.ucc.asn.au/?p=matches%2FMCTX3420.git;a=commitdiff_plain;h=ed189a5dd5b5ca6c052d75704dec3f58fe410387;hp=-c Merge branch 'master' of https://github.com/szmoore/MCTX3420.git --- ed189a5dd5b5ca6c052d75704dec3f58fe410387 diff --combined server/actuator.c index c71b05a,50a27de..f5d7cd6 --- a/server/actuator.c +++ b/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) { @@@ -53,43 -62,34 +61,43 @@@ 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]; @@@ -194,7 -197,15 +203,15 @@@ } 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 index ee0ed32,c2a229d..48e0f29 --- a/server/actuator.h +++ b/server/actuator.h @@@ -14,13 -14,14 +14,14 @@@ // 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 index a648ae8,e391fcd..67f7de3 --- a/server/fastcgi.c +++ b/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; @@@ -489,7 -490,7 +491,7 @@@ } context.response_number++; - Log(LOGDEBUG, "Waiting for request #%d", context.response_number); + } Log(LOGDEBUG, "Thread exiting."); diff --combined server/sensor.c index 64c7aa9,9d0b33c..e429958 --- a/server/sensor.c +++ b/server/sensor.c @@@ -7,6 -7,7 +7,7 @@@ #include "common.h" #include "sensor.h" #include "options.h" + #include "bbb_pin.h" #include /** 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) { @@@ -69,11 -83,9 +81,11 @@@ 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)); @@@ -81,29 -93,23 +93,29 @@@ { 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; @@@ -170,33 -200,43 +207,43 @@@ 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 index 6c7abaa,eeb6da1..182d8ae --- a/server/sensor.h +++ b/server/sensor.h @@@ -9,16 -9,18 +9,18 @@@ #include "data.h" /** Number of sensors **/ - #define NUMSENSORS 6 + #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 **/