Example code for the Programmable High-Power Infra-Red Beacon with display Designed for use with the E-Puck and Pi Swarm robots for swarm research A number of preset frequencies (1, 2, 5, 10, 20, 30, 40 and 50Hz), powers (25%, 50%, 75% and 100%), duty-cycles (10%, 25%, 50%, 75% and 90%) are defined, and the chosen mode can be selected by holding the 'SET' button for 1 seconds, then moving through to the correct menu. Use as a basic structure should other functionality be required from the beacon, such as custom flash sequencies or alternating between the wide- and narrow- LEDs.

Dependencies:   mbed

PCB Image: [NB Missing connection from pin 1-4 of display] /media/uploads/jah128/board_fin2.png

Eagle Files: /media/uploads/jah128/irledboard_pro.sch /media/uploads/jah128/irledboard_pro.brd

Corel Draw file for laser-cutting box: /media/uploads/jah128/irbox_3.cdr

Files at this revision

API Documentation at this revision

Comitter:
jah128
Date:
Wed Mar 19 15:09:11 2014 +0000
Commit message:
Initial Version

Changed in this revision

display.cpp Show annotated file Show diff for this revision Revisions of this file
display.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/display.cpp	Wed Mar 19 15:09:11 2014 +0000
@@ -0,0 +1,146 @@
+/* University of York Robotics Laboratory MBED Library
+ * Display Driver for Midas I2C 2x16 Display
+ * Part number MCCOG21605-D6W-BNMLWI
+ * Rapid Electronics Cat Number 57-2340 [or 57-2334]
+ * Farnell Cat Number 2063206 [or 2063205]
+ * 
+ * File: display.cpp
+ *
+ * (C) Dr James Hilder, Dept. Electronics & Computer Science, University of York
+ * 
+ * October 2013
+ *
+ */ 
+ 
+#include "mbed.h"
+#include "display.h"
+
+Display::Display(PinName sda, PinName scl, PinName reset) :  Stream("display"), _i2c(sda,scl), _reset(reset)  {
+  
+}
+
+Display::Display() :  Stream("display"), _i2c(p9,p10), _reset(p12)  {
+  
+}
+
+int Display::i2c_message(char byte){
+   char bytes [2];
+   bytes[0]=0x80;
+   bytes[1]=byte;
+   int ret=_i2c.write(LCD_ADDRESS,bytes,2);  
+   wait(0.01);
+   return ret;
+}
+
+int Display::disp_putc(int c){
+   char message [2];
+   message[0]=0x40;
+   message[1]=c;
+   _i2c.write(LCD_ADDRESS,message,2);
+   wait(0.01);
+   return c;
+}
+
+
+
+void Display::init_display(){
+   //Set initial states: display on, cursor off
+   display_on = 1;
+   cursor_on = 0;
+   blink_on  = 0;
+    
+   _reset=1;
+   wait(0.02);
+   //Set reset low
+   _reset=0;
+   wait(0.001);
+   _reset=1;
+   wait(0.03);
+   i2c_message(0x38); 
+   i2c_message(0x39); 
+   i2c_message(0x14); 
+   i2c_message(0x79); 
+   i2c_message(0x50); 
+   i2c_message(0x6c); 
+   _set_display();
+   clear_display(); 
+} 
+
+void Display::write_string(char * message, char length){
+   char to_send [length+1];
+   to_send[0]=0x40;
+   for(int i=0;i<length;i++){
+     to_send[i+1] = message[i];
+   }
+   _i2c.write(LCD_ADDRESS,to_send,length+1);
+}
+
+void Display::set_position(char row, char column){
+  if(row < 2 && column < 16){
+    char pos = 128 +((row * 64)+column);
+    i2c_message(pos);
+  }
+}
+
+void Display::set_cursor(char enable){
+  cursor_on=enable;
+  _set_display();
+}
+
+void Display::set_blink(char enable){
+  blink_on=enable;
+    _set_display();
+}
+
+void Display::set_display(char enable){
+  display_on=enable;
+    _set_display();
+}
+
+void Display::clear_display(){
+  i2c_message(0x01);
+}
+
+void Display::home(){
+  i2c_message(0x02);
+}
+
+
+void Display::_set_display(){
+    char mode = 8;
+    if(display_on>0) mode += 4;
+    if(cursor_on>0) mode += 2;
+    if(blink_on>0) mode ++;
+    i2c_message(mode);
+}
+
+
+int Display::_putc (int c) {
+    putc(c);
+    return(c);
+}
+
+int Display::_getc (void) {
+    char r = 0;
+    return(r);
+}
+ 
+ 
+/* Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/display.h	Wed Mar 19 15:09:11 2014 +0000
@@ -0,0 +1,114 @@
+/* University of York Robotics Laboratory MBED Library
+ * Display Driver for Midas I2C 2x16 Display
+ * Part number MCCOG21605-D6W-BNMLWI
+ * Rapid Electronics Cat Number 57-2340 [or 57-2334]
+ * Farnell Cat Number 2063206 [or 2063205]
+ * 
+ * File: display.cpp
+ *
+ * (C) Dr James Hilder, Dept. Electronics & Computer Science, University of York
+ * 
+ * October 2013
+ *
+ */ 
+ 
+#ifndef DISPLAY_H
+#define DISPLAY_H
+
+//
+// Defines
+// Address is 0111 110  (x7C)
+
+#define LCD_ADDRESS 0x7C      
+
+
+class Display : public Stream {
+
+// Public Functions
+
+public:
+
+   /** Create the LCD Display object connected to the default pins
+     *
+     * @param sda pin   - default is p9
+     * @param scl pin   - default is p10
+     * @param reset pin - default is p12
+     */
+     
+    Display();
+    
+    /** Create the LCD Display object connected to specific pins
+     *
+     */
+    Display(PinName sda, PinName scl, PinName reset);
+
+//Print string message of given length
+void write_string(char * message, char length);
+
+//Set the row and column of cursor position
+void set_position(char row, char column);
+
+// Enable or disable cursor
+void set_cursor(char enable);
+
+// Enable or disable cursor blink
+void set_blink(char enable);
+
+// Enable or disable display
+void set_display(char enable);
+
+
+// Clear display
+void clear_display();
+
+//Set cursor to home position
+void home();
+
+
+// Send a 1-byte control message to the display
+int i2c_message(char byte);
+
+// Default initialisation sequence for the display
+void init_display();
+
+int disp_putc(int c);
+
+
+private :
+
+    I2C _i2c;
+    DigitalOut _reset;
+    
+    char display_on;
+    char cursor_on;
+    char blink_on;
+    
+    void _set_display();
+    
+    virtual int _putc(int c);
+    virtual int _getc();
+    
+};
+
+#endif // DISPLAY_H
+
+ 
+ 
+/* Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Mar 19 15:09:11 2014 +0000
@@ -0,0 +1,337 @@
+/* University of York Robot Lab
+ *
+ * Programmable IR Beacon with Display Example Code
+ *
+ * This file is intended for use exclusively with the high-power IR Beacon with display
+ * 
+ * 
+ *
+ * (C) Dr James Hilder, Dept. Electronics & Computer Science, University of York
+ *
+ * March 2014
+ *
+ */
+
+#include "mbed.h"
+#include "display.h"        //Display driver for the Midas 16x2 I2C Display
+
+DigitalIn button1(p23);     //"SET" Push-button
+DigitalIn button2(p24);     //"SELECT" Push-button
+PwmOut out_narrow(p21);     //PWM Output for the narrow (high intensity) LED driver
+PwmOut out_wide(p22);       //PWM Output for the wide-angle LED driver
+
+Display display;
+Timer system_timer;         //System timer is used for timer the on-off periods for the LEDs
+Timer button_timer;         //Button timer is used for debouncing the push buttons and pausing for entering 'SET' mode
+
+char adjust = 0;
+char mode = 0;
+char power = 1;
+char duty = 2;
+char frequency = 2;
+
+int on_period;
+int off_period;
+int total_period;
+char phase;
+
+int get_period()
+{
+    switch(frequency) {
+        case 0:
+            return 1000000;
+        case 1:
+            return 500000;
+        case 2:
+            return 200000;
+        case 3:
+            return 100000;
+        case 4:
+            return 50000;
+        case 5:
+            return 33333;
+        case 6:
+            return 25000;
+        case 7:
+            return 20000;
+    }
+    return 0;
+}
+
+void update_cycles()
+{
+    total_period = get_period();
+    switch(duty){
+        case 0: on_period=total_period/10;break;
+        case 1: on_period=total_period/4;break;
+        case 2: on_period=total_period/2;break;
+        case 3: on_period=(total_period*3)/4;break;
+        case 4: on_period=total_period-(total_period/10);break;    
+    }
+    off_period = total_period - on_period;
+    phase = 0;
+    system_timer.reset();
+}
+
+void init()
+{
+    display.init_display();
+    display.set_position(0,2);
+    display.write_string("YORK ROBOTICS",13);
+    display.set_position(1,3);
+    display.write_string("LABORATORY",10);
+    wait(0.45);
+    display.clear_display();
+    display.set_position(0,2);
+    display.write_string("Programmable",12);
+    display.set_position(1,3);
+    display.write_string("IR Beacon",9);
+    wait(0.45);
+}
+
+char * mode_string()
+{
+    switch(mode) {
+        case 1:
+            return "WIDE  ";
+        case 2:
+            return "NARROW";
+    }
+    return "BOTH  ";
+}
+
+char * duty_string()
+{
+    switch(duty) {
+        case 0:
+            return " 10%";
+        case 1:
+            return " 25%";
+        case 2:
+            return " 50%";
+        case 3:
+            return " 75%";
+        case 4:
+            return " 90%";
+    }
+    return"???";
+}
+
+char * power_string()
+{
+    switch(power) {
+        case 0:
+            return " 25%";
+        case 1:
+            return " 50%";
+        case 2:
+            return " 75%";
+        case 3:
+            return "100%";
+    }
+    return"????";
+}
+
+char * freq_string()
+{
+    switch(frequency) {
+        case 0:
+            return " 1Hz";
+        case 1:
+            return " 2Hz";
+        case 2:
+            return " 5Hz";
+        case 3:
+            return "10Hz";
+        case 4:
+            return "20Hz";
+        case 5:
+            return "30Hz";
+        case 6:
+            return "40Hz";
+        case 7:
+            return "50Hz";
+    }
+    return "????";
+}
+
+// The normal mode display output: shows the frequency, power, duty-cycle and output mode (ie wide, narrow or both)
+void display_status()
+{
+    display.clear_display();
+    display.set_position(0,0);
+    char line1[15] ;
+    strcpy(line1, "F:");
+    strcat(line1, freq_string());
+    strcat(line1, " P:");
+    strcat(line1, power_string());
+    display.write_string(line1,13);
+    char line2[17];
+    strcpy(line2, "D:");
+    strcat(line2, duty_string());
+    strcat(line2, " M:");
+    strcat(line2, mode_string());
+    display.set_position(1,0);
+    display.write_string(line2,16);
+}
+
+// The configuration mode; entered by holding the 'set' button for one second.  In this mode the user can through the options
+// by pressing 'set' and change a setting by pressing 'select'.  The final screen in the loop allows the user to return to
+// normal operation, this will also happen with no user input for 5 seconds.
+void change_settings()
+{
+    //Switch off LEDs whilst in configuration mode 
+    out_wide.pulsewidth_us(0);
+    out_narrow.pulsewidth_us(0);
+    display.clear_display();
+    display.set_position(0,0);
+    display.write_string("CONFIGURATION",13);
+    display.set_position(1,0);
+    display.write_string("MODE",4);
+    while(button1 == 1);
+    char screen = 0;
+    char active = 1;
+    Timer settings_timer;
+    settings_timer.start();
+    while(active) {
+        display.clear_display();
+        display.set_position(0,0);
+        char line2[17];
+        switch(screen) {
+            case 0:
+                display.write_string("Set Frequency:",14);
+                display.set_position(1,0);
+                strcpy(line2,freq_string());
+                display.write_string(line2,4);
+                break;
+            case 1:
+                display.write_string("Set Power:    ",14);
+                display.set_position(1,0);
+                strcpy(line2,power_string());
+                display.write_string(line2,4);
+                break;
+            case 2:
+                display.write_string("Set Duty Cycle:",15);
+                display.set_position(1,0);
+                strcpy(line2,duty_string());
+                display.write_string(line2,4);
+                break;
+            case 3:
+                display.write_string("Set Mode:     ",14);
+                display.set_position(1,0);
+                strcpy(line2,mode_string());
+                display.write_string(line2,6);
+                break;
+            case 4:
+                display.write_string("End Setup",9);
+                break;
+        }
+        char button_pressed = 0;
+        
+        while(button_pressed < 2 && settings_timer.read_ms() < 5000){
+            if(button1 == 1 || button2 == 1){
+                if(button_pressed == 1){
+                    if(button_timer.read_ms() > 50) button_pressed = 2;
+                } else {button_pressed = 1; button_timer.reset();}
+            }  else button_pressed = 0;
+        }
+        if(button1==1){
+            screen++;
+            if(screen == 5)screen=0;
+            while(button1 == 1);
+        }else{
+          if(button2==1){
+            switch(screen){
+               case 0: frequency ++;
+                       if(frequency == 8) frequency = 0;
+                       break;
+               case 1: power++;
+                       if(power == 4) power=0;
+                       break;
+               case 2: duty++;
+                       if(duty == 5) duty=0;
+                       break;
+               case 3: mode++;
+                       if(mode == 3) mode = 0;
+                       break;
+               case 4: active=0; break;
+            }
+            while(button2 == 1);   
+          }   
+        }
+        if(settings_timer > 5000) active=0;
+        settings_timer.reset();
+    }
+}
+
+int main()
+{
+    init();
+    display_status();
+    char b_p = 0;
+    system_timer.start();
+    button_timer.start();
+    update_cycles();
+    out_narrow.period_us(1000);
+    out_wide.period_us(1000);
+    out_narrow.pulsewidth_us(0);
+    out_wide.pulsewidth_us(0);
+
+
+    while(1) {
+        if(phase==0){
+          if(system_timer.read_us() > off_period){
+            system_timer.reset();
+            int pw = 250;
+            if(power==1) pw=500;
+            if(power==2) pw=750;
+            if(power==3) pw=1000;
+            if(mode<2){
+                out_wide.pulsewidth_us(pw);
+            } 
+            if(mode!=1){
+                out_narrow.pulsewidth_us(pw);
+            }
+            phase = 1;
+          }
+        }else{
+          if(system_timer.read_us() > on_period){
+            system_timer.reset();
+            phase = 0;
+            out_wide.pulsewidth_us(0);
+            out_narrow.pulsewidth_us(0);
+          }   
+        }
+        
+        
+        if(button1 == 1) {
+            if(b_p == 0) {
+                b_p=1;
+                button_timer.reset();
+            }
+            if(b_p == 1) {
+                if(button_timer.read_ms() > 100) {
+                    b_p=2;
+                    display.clear_display();
+                    display.set_position(0,0);
+                    display.write_string("Hold to change",14);
+                    display.set_position(1,0);
+                    display.write_string("settings",8);
+                }
+            }
+            if(b_p == 2) {
+                if(button_timer.read_ms() > 1000) {
+                    change_settings();
+                    update_cycles();
+                    display_status();
+                    b_p=0;
+                }
+            }
+        } else {
+            if (b_p > 0) {
+                if(b_p == 2) display_status();
+                b_p=0;
+            }
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Wed Mar 19 15:09:11 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/9114680c05da