/* Arduino demo SPI code for 16X PWM LED FADER support@CuriousInventor.com (c) 2011, Curious Inventor, LLC Instructions: check out read_serial_port() for some examples change log: 1/14/11 - initial release */ char print_text[60] = "16X PWM LED FADER demo SPI arduino control, v1.0, 1/14/11"; // __________ DEFINES __________________________________________ //#define SERIAL_DEBUGGING #define BAUD 38400 #define DATAOUT 11//MOSI #define DATAIN 12//MISO #define SPICLOCK 13//sck #define SLAVESELECT 10//ss #define SERIAL 1 #define LED_STATUS 2 // pot_mappings: #define G2_BRIGHTNESS 1 #define G2_SUNSPOT_POS 2 #define LIGHT_13_BRIGHTNESS 3 // __________ INCLUDES __________________________________________ #include // __________ GLOBAL VARIABLES __________________________________________ char pot_mapping = 0; long led_blink_time = 0; unsigned long spi_check_time = 0; char spi_out_buf[100]; // __________ PROTOTYPES __________________________________________ void read_serial_port(void); char get_spi_response_code(void); void blink_led(void); char spi_transfer(volatile char); unsigned int send_spi(unsigned char command, unsigned int d1, unsigned int d2); void keep_checking_spi(void); void send_continuous_commands(void); void store_lights_1_thru_8_into_g(int group); void set_brightness_group(int group, unsigned int level); void apply_sunspot_to_group(int group, int center, int s_width, int start, int s_end, unsigned int brightness); void start_sweep_group(int group, int s_width, int start, int s_end, unsigned int brightness, unsigned int repeat_time, unsigned int time, int s_mode, int dir); void start_chase_group(int group, unsigned int brightness, unsigned int step_time, unsigned int low_brightness, unsigned int fading_on_time, unsigned int fading_off_time, unsigned int on_time,unsigned int repeat_time); void store_lights_9_thru_11_into_g(int group); void start_random_blink_group(int group, unsigned int brightness, unsigned int step_time, unsigned int low_brightness, unsigned int fading_on_time, unsigned int fading_off_time, unsigned int on_time); void start_blink_group(int group, unsigned int brightness,unsigned int low_brightness, unsigned int fading_on_time, unsigned int fading_off_time, unsigned int on_time, unsigned int off_time); void start_blink_light(int group, unsigned int brightness,unsigned int low_brightness, unsigned int fading_on_time, unsigned int fading_off_time, unsigned int on_time, unsigned int off_time); //____________ FUNCTIONS ________________________________________________ //_________________ S E T U P ___________________________________________ // void setup() { int i,j; digitalWrite(SLAVESELECT, HIGH); pinMode(DATAOUT, OUTPUT); pinMode(SPICLOCK,OUTPUT); pinMode(SLAVESELECT,OUTPUT); // // turn on SPI module SPCR = 0b01010000; // fosc / 4 = 4MHz // SPCR = 0b01010011; // 128kHz pinMode(9, OUTPUT); pinMode(LED_STATUS,OUTPUT); if (SERIAL) { Serial.begin(BAUD); } Serial.println(print_text); #ifndef SERIAL_DEBUGGING Serial.print("\n\nDemos:\n\n"); Serial.print("a:\tSet brightness of light #15 to 5000 \n"); Serial.print("b:\tSet brightness of light #15 to 50000 \n"); Serial.print("c:\tAssign lights 1-8 to group g2\n"); Serial.print("d:\tSet brightness of group g2 to 2000\n"); Serial.print("e:\tSet brightness of group g2 to 65528\n"); Serial.print("f:\tControl group g2's brightness with pot (analog A0)\n"); Serial.print("g:\tApply sunspot to g2, centered\n"); Serial.print("h:\tControl center of sunspot on g2 with pot (Analog A0)\n"); Serial.print("i:\tStart cylon style sweep on group g2\n"); Serial.print("j:\tStart chase on group g2\n"); Serial.print("k:\tStart fast chase on group g2\n"); Serial.print("l:\tgroup 9-11 into g3, start slow chase on g3\n"); Serial.print("m:\tStart random blink on group g2\n"); Serial.print("n:\tStart breathing fade on group g2\n"); Serial.print("o:\tStart triangle fade on light 15\n"); Serial.print("p:\tStart fast blink on light 15\n"); Serial.print("q:\tStart breathing fade on light 15\n"); Serial.print("r:\tSet lights 14 and 15 to max brightness\n"); Serial.print("s:\tMap pot to light 13 brightness\n"); Serial.print("z:\tall off\n"); #else Serial.println("\nSerial debugging mode: serial commands will be passed directly through to spi\n"); #endif delay(50); } // ___________________________________ L O O P ______________________________________________ void loop() { read_serial_port(); blink_led(); // map(val, 0, 1023, 0, 255); send_continuous_commands(); // used if the pot is mapped to commands #ifdef SERIAL_DEBUGGING keep_checking_spi(); #endif delay(1); } void send_continuous_commands() { unsigned int pot_value; pot_value = analogRead(0); // 0 to 1023 if (pot_mapping == G2_BRIGHTNESS) { pot_value = map(pot_value,0,1023,8,65528); set_brightness_group(2,pot_value); } else if (pot_mapping == G2_SUNSPOT_POS) { pot_value = map(pot_value,0,1023,0,1000); // apply_sunspot_to_group(int group, int center, int s_width, int start, int s_end, unsigned int brightness) apply_sunspot_to_group(2, pot_value, 300, 150, 850, 65528); } else if (pot_mapping == LIGHT_13_BRIGHTNESS) { pot_value = map(pot_value,0,1023,8,65528); set_brightness(13,pot_value); } } void start_blink_light(int light, unsigned int brightness, unsigned int low_brightness, unsigned int fading_on_time, unsigned int fading_off_time, unsigned int on_time, unsigned int off_time) { unsigned char size; size = sprintf(spi_out_buf,"b;%u;v;%u;u;%u;y;%u;o;%u;f;%u;",brightness,low_brightness,fading_on_time,fading_off_time,on_time,off_time); send_spi_string(size); size = sprintf(spi_out_buf,"T;%d;",light); send_spi_string(size); } void start_blink_group(int group, unsigned int brightness, unsigned int low_brightness, unsigned int fading_on_time, unsigned int fading_off_time, unsigned int on_time, unsigned int off_time) { unsigned char size; size = sprintf(spi_out_buf,"b;%u;v;%u;u;%u;y;%u;o;%u;f;%u;",brightness,low_brightness,fading_on_time,fading_off_time,on_time,off_time); send_spi_string(size); size = sprintf(spi_out_buf,"T;g%d;",group); send_spi_string(size); } // randomly blink lights--see chase or blink for parameter definitions void start_random_blink_group(int group, unsigned int brightness, unsigned int step_time, unsigned int low_brightness, unsigned int fading_on_time, unsigned int fading_off_time, unsigned int on_time) { unsigned char size; size = sprintf(spi_out_buf,"b;%u;t;%u;v;%u;u;%u;y;%u;o;%u;",brightness,step_time,low_brightness,fading_on_time,fading_off_time,on_time); send_spi_string(size); size = sprintf(spi_out_buf,"R;g%d;",group); send_spi_string(size); } // each light in the sequence fades from low_brightness to brightness over fading_on_time, then stays there for on_time, then fades to low_brightess over fading_off_time void start_chase_group(int group, unsigned int brightness, unsigned int step_time, unsigned int low_brightness, unsigned int fading_on_time, unsigned int fading_off_time, unsigned int on_time,unsigned int repeat_time) { unsigned char size; size = sprintf(spi_out_buf,"b;%u;t;%u;v;%u;u;%u;y;%u;o;%u;x;%u;",brightness,step_time,low_brightness,fading_on_time,fading_off_time,on_time,repeat_time); send_spi_string(size); size = sprintf(spi_out_buf,"C;g%d;",group); send_spi_string(size); } void start_sweep_group(int group, int s_width, int start, int s_end, unsigned int brightness, unsigned int repeat_time, unsigned int time, int s_mode, int dir) { unsigned char size; // see apply_sunspot_to_group for add'l parameter defs // s_mode: 0: continuous, 1: continous/reverse, 2: repeat after time (time isn't used for modes 0,1,4,5) // 3: repeat after time / reverse, 4: single sweep // repeat_time: in modes 2,3, time before it starts again in ms // dir: sweep direction: 1 for forward, 0 for reverse // time: sweep duration in ms // set Sweep parameters size = sprintf(spi_out_buf,"b;%u;w;%d;r;%d;l;%d;x;%u;s;%u;m;%d;d;%d;",brightness,s_width,s_end,start,repeat_time,time,s_mode,dir); send_spi_string(size); //apply Sweep to group: size = sprintf(spi_out_buf,"S;g%d;",group); send_spi_string(size); } // a sunspot sets a bright spot in a group of lights, fading from the center to 1/2 the width on either side void apply_sunspot_to_group(int group, int center, int s_width, int start, int s_end, unsigned int brightness) { unsigned char size; // first set the parameters, then apply to the group // center: 0 - 1000 over the group, so 500 would be the center // width: if 200, the lights will fade from off to on from 100 on either side of the center // start: in order to be able to start with all lights off, this sets the position of the first light. // If the width is 200, center 100, and start also 100, the first light will be off. If start is 0, the first // light will be full on. // end: defines the position of the last light. size = sprintf(spi_out_buf,"c;%d;b;%u;w;%d;r;%d;l;%d;",center,brightness,s_width,s_end,start); send_spi_string(size); size = sprintf(spi_out_buf,"N;g%d;",group); send_spi_string(size); } void store_lights_1_thru_8_into_g(int group) { unsigned char size; size = sprintf(spi_out_buf,"G;g%d;1;2;3;4;5;6;7;8;",group); send_spi_string(size); } void store_lights_9_thru_11_into_g(int group) { unsigned char size; size = sprintf(spi_out_buf,"G;g%d;9;10;11;",group); send_spi_string(size); } void set_brightness_group(int group, unsigned int level) { unsigned char size; size = sprintf(spi_out_buf,"b;%u;B;g%d;",level,group); send_spi_string(size); } // sets the brightness of an individual light, or 0 for all void set_brightness(int light, unsigned int level) { int error = 0; unsigned char size; size = sprintf(spi_out_buf,"b;%u;B;%d;",level,light); send_spi_string(size); // to get error-feeback on each command, uncomment the following and comment out the above: /* if (light >= 0 && light <= 16) { spi_transfer('b'); spi_transfer(';'); error += get_spi_response_code(); if (error != 0) { Serial.print("error1: ");Serial.println(error); } size = sprintf(spi_out_buf,"%u;",level); send_spi_string(size); error = get_spi_response_code(); if (error) { Serial.print("error2: ");Serial.println(error); } spi_transfer('B'); spi_transfer(';'); error = get_spi_response_code(); if (error) { Serial.print("error3: ");Serial.println(error); } size = sprintf(spi_out_buf,"%d;",light); send_spi_string(size); error = get_spi_response_code(); if (error) { Serial.print("error4: ");Serial.println(error); } } else { Serial.print("bad input: set_brightness "); Serial.print(light);Serial.print(" ");Serial.print(level);Serial.print(" ");Serial.println(error); } */ } void send_spi_string(int s) { int i = 0; for (i;i 200) { led_blink_time = millis(); digitalWrite(LED_STATUS, !digitalRead(LED_STATUS)); } } // ___________________________________ R E A D S E R I A L P O R T ______________________________________________ void read_serial_port() { unsigned char input_char; while (Serial.available()) { input_char = Serial.read(); #ifndef SERIAL_DEBUGGING if (input_char == 'a') { set_brightness(15,5000); // light: 0-16 (0=all), brightness: 0-65528 } else if (input_char == 'b') { set_brightness(15,50000); } else if (input_char == 'c') { store_lights_1_thru_8_into_g(2); } else if (input_char == 'd') { set_brightness_group(2,2000); } else if (input_char == 'e') { set_brightness_group(2,65528); } else if (input_char == 'f') { // toggle pot control over the brightness of G2 if (pot_mapping == G2_BRIGHTNESS) pot_mapping = 0; else pot_mapping = G2_BRIGHTNESS; } else if (input_char == 'g') { // apply_sunspot_to_group(int group, int center, int s_width, int start, int s_end, unsigned int brightness) apply_sunspot_to_group(2, 500, 300, 100, 900, 65528); } else if (input_char == 'h') { if (pot_mapping == G2_SUNSPOT_POS) pot_mapping = 0; else pot_mapping = G2_SUNSPOT_POS; } else if (input_char == 'i') { //void start_sweep_group(int group, int s_width, int start, int s_end, unsigned int brightness, unsigned int repeat_time, unsigned int time, int s_mode, int dir) start_sweep_group(2, 350, 200, 800, 65528, 2200, 2000, 3, 1); } else if (input_char == 'j') { // void start_chase_group(int group, unsigned int brightness, unsigned int step_time, unsigned int low_brightness, unsigned int fading_on_time, unsigned int fading_off_time, unsigned int on_time,unsigned int repeat_time) start_chase_group(2,65528,200,0,250,250,100,850); } else if (input_char == 'k') { start_chase_group(2,65528,80,0,0,0,80,350); } else if (input_char == 'l') { store_lights_9_thru_11_into_g(3); start_chase_group(3,65528,2000,0,4000,4000,0,8000); } else if (input_char == 'm') { // start_random_blink_group(int group, unsigned int brightness, unsigned int step_time, unsigned int low_brightness, unsigned int fading_on_time, unsigned int fading_off_time, unsigned int on_time, unsigned int repeat_time) start_random_blink_group(2, 65528,160,0,0,0,160); } else if (input_char == 'n') { // start_blink_group(int group, unsigned int brightness, unsigned int low_brightness, unsigned int fading_on_time, unsigned int fading_off_time, unsigned int on_time, unsigned int off_time) { start_blink_group(2,65528,400,800,3500,400,0); } else if (input_char == 'o') { // start_blink_light(int light, unsigned int brightness, unsigned int low_brightness, unsigned int fading_on_time, unsigned int fading_off_time, unsigned int on_time, unsigned int off_time) { start_blink_light(15,65528,0,1000,0,0,500); } else if (input_char == 'p') { // start_blink_light(int light, unsigned int brightness, unsigned int low_brightness, unsigned int fading_on_time, unsigned int fading_off_time, unsigned int on_time, unsigned int off_time) { start_blink_light(15,65528,0,0,0,160,160); } else if (input_char == 'q') { // start_blink_light(int light, unsigned int brightness, unsigned int low_brightness, unsigned int fading_on_time, unsigned int fading_off_time, unsigned int on_time, unsigned int off_time) { start_blink_light(15,65528,400,800,3500,400,000); } else if (input_char == 'r') { // start_blink_light(int light, unsigned int brightness, unsigned int low_brightness, unsigned int fading_on_time, unsigned int fading_off_time, unsigned int on_time, unsigned int off_time) { set_brightness(16,65528); set_brightness(14,65528); } else if (input_char == 's') { if (pot_mapping == LIGHT_13_BRIGHTNESS) pot_mapping = 0; else pot_mapping = LIGHT_13_BRIGHTNESS; } else if (input_char == 'z') { set_brightness_group(2,0); set_brightness_group(3,0); set_brightness(0,0); // 0 is for all } #else // for debugging: (be sure to uncomment #define SERIAL_DEBUGGING at the top // Pass serial commands straight through to SPI, print out response codes. // Try uncommenting this and sending commands like: // b; // 15000; // B; // 3; // to see individual response codes for debugging. input_char = spi_transfer(input_char); // pass if (input_char != 0xFF) Serial.println(input_char,HEX); // check do { input_char = spi_transfer(0xFF); // pass if (input_char != 0xFF) Serial.println(input_char,HEX); } while (input_char != 0xFF); #endif } } void keep_checking_spi() { unsigned char input_char; if (millis() - spi_check_time > 100) { spi_check_time = millis(); do { input_char = spi_transfer(0xFF); // pass if (input_char != 0xFF) Serial.println(input_char,HEX); } while (input_char != 0xFF); } } char spi_transfer(volatile char data) { // Serial.println(data,DEC); digitalWrite(SLAVESELECT,0); SPDR = data; // Start the transmission while (!(SPSR & (1<