Lab 6 - Step 3: Add Detection of Hardware Failure

Fork of ADCandticker_sample by William Marsh

Revision:
3:c6c88a1a58a8
Parent:
2:de96c8c234b6
--- a/main.cpp	Thu Mar 08 14:41:22 2018 +0000
+++ b/main.cpp	Fri Mar 09 15:19:12 2018 +0000
@@ -1,46 +1,99 @@
+#include "mbed.h"
+#include "rtos.h"
+#include "wdt.h"
 
-// LAB 3 SAMPLE PROGRAM 1
-//   Revised for mbed 5
+// Sample program using the Watchdog
+// ---------------------------------
+//    * Three threads co-operate to flash two LEDs
+//    * A simple way to inject a fault, by pressing a button
+//    * The watchdog is configured with a 32ms timeout
 
-#include "mbed.h"
+#define ON 1
+#define OFF 0
+DigitalOut led_red(LED_RED, ON);
+DigitalIn button(PTD0, PullUp);
+DigitalOut led1(PTC12, OFF);
+DigitalOut led2(PTC13, OFF);
+
+AnalogIn ain1(A0) ; // Analog input
+AnalogIn ain2(A1) ; // Analog input
+Serial pc(USBTX, USBRX); // tx, rx, for debugging
 
 
-Ticker tick;                // Ticker for reading analog
-AnalogIn ain(A0) ;          // Analog input
-DigitalOut led1(LED_RED);   // Red LED
+// This ticker is used to feed the watch dog
+Ticker tick;
+
+// Threads
+Thread threadT(osPriorityNormal, 2000) ; // timer thread
+Thread threadLED1(osPriorityNormal, 2000) ; // thread LED1
+Thread threadLED2(osPriorityNormal, 2000) ; // thread LED2
 
-Serial pc(USBTX, USBRX); // tx, rx, for debugging
+// ------------Fault Injection Button-------------
+//  Wait while the button is down
+//     Use this to simulate a STUCK fault
+// -----------------------------------------------
+void waitButton()
+{
+    while (!button) ;
+}
 
 // Message type
 typedef struct {
-  uint16_t analog; /* Analog input value */
+    uint16_t analog; /* Analog input value */
 } message_t;
 
 // Mail box
-Mail<message_t, 2> mailbox;
+Mail<message_t, 2> mailbox_led1;
 
 // Function called every 10ms to read ADC
-// Low pass filter  
+// Low pass filter
 // Every 10th value is sent to mailbox
-volatile int samples = 0 ;
-volatile uint16_t smoothed = 0 ; 
-void readA0() {
-    smoothed = (smoothed >> 1) + (ain.read_u16() >> 1) ; // divided by 2 - reduce the signal noise
-    samples++ ;
-    if (samples == 10) {
+volatile int samples_led1 = 0 ;
+volatile uint16_t smoothed_led1 = 0 ;
+void readA0()
+{
+    smoothed_led1 = (smoothed_led1 >> 1) + (ain1.read_u16() >> 1) ; // divided by 2 - reduce the signal noise
+    samples_led1++ ;
+    if (samples_led1 == 10) {
         // send to thread
-        message_t *mess = mailbox.alloc() ; // may fail but does not block
+        message_t *mess = mailbox_led1.alloc() ; // may fail but does not block
         if (mess) {
-            mess->analog = smoothed ;
-            mailbox.put(mess); // fails but does not block if full
+            mess->analog = smoothed_led1;
+            mailbox_led1.put(mess); // fails but does not block if full
         }
-        samples = 0;
-    }       
+        samples_led1 = 0;
+    }
 }
 
+// Mail box
+Mail<message_t, 2> mailbox_led2;
+
+// Function called every 10ms to read ADC
+// Low pass filter
+// Every 10th value is sent to mailbox
+volatile int samples_led2 = 0 ;
+volatile uint16_t smoothed_led2 = 0 ;
+void readA1()
+{
+    smoothed_led2 = (smoothed_led2 >> 1) + (ain2.read_u16() >> 1) ; // divided by 2 - reduce the signal noise
+    samples_led1++ ;
+    if (samples_led2 == 10) {
+        // send to thread
+        message_t *mess = mailbox_led2.alloc() ; // may fail but does not block
+        if (mess) {
+            mess->analog = smoothed_led2;
+            mailbox_led2.put(mess); // fails but does not block if full
+        }
+        samples_led2 = 0;
+    }
+}
+
+
+
 // Write voltage digits
 //   v  Voltage as scale int, e.g. 3.30 is 330
-void vToString(int v, char* s) {    
+void vToString(int v, char* s)
+{
     s[3] = '0' + (v % 10) ;
     v = v / 10 ;
     s[2] = '0' + (v % 10) ;
@@ -48,36 +101,140 @@
     s[0] = '0' + (v % 10) ;
 }
 
-// Main program
-//   Initialise variables
-//   Attach ISR for ticker
-//   Procss messages from mailbox    
-int main() {
-    led1 = 1 ; // turn off 
+// ---Thread for controlling LED 1----------------
+//   Turn LED1 on/off in response to signals
+// -----------------------------------------------
+void led1_thread()    // method to run in thread
+{
+    osEvent evt ;
+    while (true) {
+        evt = Thread::signal_wait(0x0); // wait for any signal
+        if (evt.status == osEventSignal) {
+            if (evt.value.signals & 0x01) led1 = ON ;
+            if (evt.value.signals & 0x02) led1 = OFF ;
+        }
+        waitButton() ;  // POSSIBLE FAULT HERE
+        wdt_kickA();
+    }
+}
+
+// ---Thread for controlling LED 2----------------
+//   Turn LED2 on/off in response to signals
+// -----------------------------------------------
+void led2_thread()    // method to run in thread
+{
+    osEvent evt ;
+    while (true) {
+        evt = Thread::signal_wait(0x0); // wait for any signal
+        if (evt.status == osEventSignal) {
+            if (evt.value.signals & 0x01) led2 = ON ;
+            if (evt.value.signals & 0x02) led2 = OFF ;
+        }
+        //waitButton() ; // POSSIBLE FAULT HERE
+        wdt_kickB();
+    }
+}
+
+// ---Thread for timing --------------------------
+//   Send signals to the other threads
+// -----------------------------------------------
+void timer_thread()    // method to run in thread
+{
+    while (true) {
+        Thread::wait(250) ;
+        threadLED1.signal_set(0x1) ;
+        threadLED2.signal_set(0x1) ;
+        Thread::wait(250) ;
+        threadLED1.signal_set(0x2) ;
+        threadLED2.signal_set(0x2) ;
+        //waitButton() ; // POSSIBLE FAULT HERE
+    }
+}
+
+// -----------MAIN-------------------------------
+//    Configure watchdog. Start threads.
+//    Show start up with RED for 1sec
+//    Remember the watchdog is running
+//       - 1024ms to set it once
+//       - then must feed it every 32ms
+// ----------------------------------------------
+
+int main(void)
+{
+    wdt_1sec() ; // initialise watchdog - 32ms timeout
+    //tick.attach_us(callback(&wdt_kick_all), 20000); // ticks every 20ms
+
+    // start threads
+    threadT.start(&timer_thread) ; // start the timer thread
+    threadLED1.start(&led1_thread) ; // start the LED1 control thread
+    threadLED2.start(&led2_thread) ; // start the LED2 control thread
+
     int volts = 0 ;
     const int threshold = 100 ; // 1 vol
-    int counter = 0 ;
+    int counter1 = 0 ;
+    int counter2 = 0 ;
     char vstring[] = "X.XX\r\n" ;
 
     tick.attach_us(callback(&readA0), 10000); // ticks every 10ms -> 10000 micro second
+//    tick.attach_us(callback(&readA1), 10000); // ticks every 10ms -> 10000 micro second
+
+    // show start-up
+    led_red = OFF;
+    Thread::wait(1000) ;
+    led_red = ON;
+
     while (true) {
-        osEvent evt = mailbox.get(); // wait for mail 
-        
+
+        // LED1 process
+        osEvent evt1 = mailbox_led1.get(); // wait for mail
         // every 100 ms this loop operates
-        if (evt.status == osEventMail) {
-            message_t* mess = (message_t*)evt.value.p ;
+        if (evt1.status == osEventMail) {
+            message_t* mess = (message_t*)evt1.value.p ;
             volts = (mess->analog * 330) / 0xffff ; // 2 ^ 16
-            mailbox.free(mess) ;  // free the message space
-            if (volts > threshold) led1 = 0 ; else led1 = 1 ;
+            mailbox_led1.free(mess) ;  // free the message space
+            counter1++;
+
+
+
             vToString(volts, vstring) ;
-            counter++ ;
-            
             // every 1 s this loop will operate
-            if (counter == 10) {  // limit bandwidth of serial
+            if (counter1 == 10) {  // limit bandwidth of serial
                 pc.printf(vstring) ;
-                counter = 0 ;
+                 if(volts >= 150-threshold && volts <= 150+threshold) {
+                    pc.printf("LED1 - Nomral \r\n\r\n") ;
+                } else if (volts == 0) {
+                    pc.printf("LED1 - open circuit \r\n\r\n") ;
+                } else if(volts > 300) {
+                    pc.printf("LED1 - short circuit \r\n\r\n") ;
+                }
+                counter1 = 0 ;
             }
         }
+        
+        // LED2 process
+        if(false) {
+        osEvent evt2 = mailbox_led2.get(); // wait for mail
+        // every 100 ms this loop operates
+        if (evt2.status == osEventMail) {
+            message_t* mess = (message_t*)evt2.value.p ;
+            volts = (mess->analog * 330) / 0xffff ; // 2 ^ 16
+            mailbox_led1.free(mess) ;  // free the message space
+            vToString(volts, vstring) ;
+            counter2++;
 
+            // every 1 s this loop will operate
+            if (counter2 == 10) {  // limit bandwidth of serial
+                pc.printf(vstring) ;
+                 if(volts >= 150-threshold && volts <= 150+threshold) {
+                    pc.printf("LED2 - Nomral \r\n\r\n") ;
+                } else if (volts == 0) {
+                    pc.printf("LED2 - open circuit \r\n\r\n" ) ;
+                } else if(volts > 300) {
+                    pc.printf("LED2 - short circuit \r\n\r\n") ;
+                }
+                counter2 = 0 ;
+            }
+        }
+        }
     }
-}
+}
\ No newline at end of file