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.
PCB Image: [NB Missing connection from pin 1-4 of display]
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
Revision 0:d88fd55a27a6, committed 2014-03-19
- Comitter:
- jah128
- Date:
- Wed Mar 19 15:09:11 2014 +0000
- Commit message:
- Initial Version
Changed in this revision
diff -r 000000000000 -r d88fd55a27a6 display.cpp --- /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
diff -r 000000000000 -r d88fd55a27a6 display.h --- /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
diff -r 000000000000 -r d88fd55a27a6 main.cpp --- /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
diff -r 000000000000 -r d88fd55a27a6 mbed.bld --- /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