// // Arduino Digital Light Wand + SD + LCD V1.04A (LPD8806) // by Is0-Mick 2012 // //This version supports direct reading of a 24bit BMP from the SD card. //You need to rotate the image 90 degrees right, due to lack of memory / speed to process //this on the fly... // // // Fixed a strange problem with 1 green pixel being left on if the last line of the image // or last pixel was not black. Apparently seems to be a known hardware / library bug... // // Tidied up code // // Fixed Backlight Problem // // Fixed the SD init problem (removing card, trying to send a file (which fails) now re-inits the card. // Backlight now fades out, instead of just switching off. // // Changed one of the original values of the shields key values, as it was thinking you were pressing a different // button sometimes, so changed the 535 value to 600 which seems to fix that :) // // Added code for an external switch to show the bitmap so you don't have fiddle with the small button on the shield // Pins are defined as aux button. I pulled one low as a GND, and the other is the trigger.(pins 44,45 currently) #include #include #include #include #define BACKLIGHT 10 #define SDssPin 53 //SD card CS pin int frameDelay = 10; // default for the frame delay LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //Init the LCD int dataPin = 31; int clockPin = 32; #define STRIP_LENGTH 52 LPD8806 strip = LPD8806(STRIP_LENGTH, dataPin, clockPin); //BacklightControl to save battery Life boolean BackLightTimer = false; int BackLightTimeout = 2000; int BackLightTemp = BackLightTimeout; //Stuff for the Keypad //int adc_key_val[5] ={ // 30, 150, 360, 535, 760 }; int adc_key_val[5] ={ 30, 150, 360, 600, 760 }; int NUM_KEYS = 5; int adc_key_in; int key=-1; int oldkey=-1; //AuxButton is a seperate button to send the image. Connect wires to these pins to use it. int AuxButton = 44; int AuxButtonGND = 45; File root; File dataFile; String m_CurrentFilename = ""; int m_FileIndex = 0; int m_NumberOfFiles = 0; String m_FileNames[200]; //yep this is bad, but unless you are going to have over 200 images on your lightwand.. long buffer[STRIP_LENGTH]; void setup() { Serial.begin(115200); pinMode(AuxButton, INPUT); digitalWrite(AuxButton,HIGH); pinMode(AuxButtonGND, OUTPUT); digitalWrite(AuxButtonGND,LOW); setupLEDs(); setupLCDdisplay(); setupSDcard(); BackLightOn(); } void setupLEDs() { strip.begin(); strip.show(); } void setupLCDdisplay() { lcd.begin(16,2); lcd.print(" *** DLW ***"); lcd.setCursor(0, 1); lcd.print("Initializing..."); delay(1000); lcd.clear(); } void setupSDcard() { pinMode(SDssPin, OUTPUT); while (!SD.begin(SDssPin)) { BackLightOn(); lcd.print("SD init failed!"); delay(1000); lcd.clear(); delay(500); } lcd.clear(); lcd.print("SD init done."); delay(1000); root = SD.open("/"); lcd.clear(); lcd.print("Scanning files"); delay(500); GetFileNamesFromSD(root); isort(m_FileNames, m_NumberOfFiles); m_CurrentFilename = m_FileNames[0]; DisplayCurrentFilename(); } int ReadKeypad() { adc_key_in = analogRead(0); // read the value from the sensor digitalWrite(13, HIGH); key = get_key(adc_key_in); // convert into key press Serial.print("key read = "); Serial.println(adc_key_in,DEC); if (key != oldkey) // if keypress is detected { delay(50); // wait for debounce time adc_key_in = analogRead(0); // read the value from the sensor key = get_key(adc_key_in); // convert into key press if (key != oldkey) { oldkey = key; if (key >=0){ return key; } } } return key; } // Convert ADC value to key number int get_key(unsigned int input) { int k; for (k = 0; k < NUM_KEYS; k++) { if (input < adc_key_val[k]) { return k; } } if (k >= NUM_KEYS) k = -1; // No valid key pressed return k; } //The Main menu starts here... void loop() { int keypress = ReadKeypad(); if ( keypress == 1) //up key (step up through the filenames) { BackLightOn(); if (m_FileIndex > 0) { m_FileIndex--; } else { m_FileIndex = m_NumberOfFiles -1; //wrap round to the last file } DisplayCurrentFilename(); delay(500); } if ( keypress == 2) //down key (step down through the filenames) { BackLightOn(); if (m_FileIndex < m_NumberOfFiles -1) { m_FileIndex++; } else { m_FileIndex = 0;//wrap round to the 1st file again } DisplayCurrentFilename(); delay(500); } //Serial.print(digitalRead(AuxButton),DEC);//for displaying the key values if ((keypress == 4) || (digitalRead(AuxButton) == LOW))//select key (send out the selected file) { SendFile(m_CurrentFilename); } if(keypress == 0) //right key (frame delay +) { BackLightOn(); if (frameDelay < 200) { frameDelay+=5; } ShowFrameDelay(); } if(keypress == 3)//left key (frame delay -) { BackLightOn(); if (frameDelay > 5) { frameDelay-=5; } ShowFrameDelay(); } if (BackLightTimer == true) BackLightTime(); } void BackLightOn() { analogWrite(BACKLIGHT,255); BackLightTimer = true; BackLightTemp = BackLightTimeout; } void BackLightTime() { if ((BackLightTemp <= 255) && (BackLightTemp >= 0)) { analogWrite(BACKLIGHT,BackLightTemp); delay(1); } if (BackLightTemp <= 0) { BackLightTimer = false; BackLightTemp = BackLightTimeout; analogWrite(BACKLIGHT,0); } else { BackLightTemp --; delay(1); } } void ShowFrameDelay() { lcd.clear(); lcd.print("Frame delay:"); lcd.setCursor(0,1); lcd.print(frameDelay); delay(500); DisplayCurrentFilename(); } void SendFile(String Filename) { lcd.clear(); lcd.print("Sending File"); lcd.setCursor(0, 1); lcd.print(Filename); char temp[14]; Filename.toCharArray(temp,14); dataFile = SD.open(temp); // if the file is available send it to the LED's if (dataFile) { ReadTheFile(); dataFile.close(); ClearStrip(100); } else { lcd.clear(); lcd.print(" Error reading"); lcd.setCursor(4, 1); lcd.print("file"); BackLightOn(); delay(1000); lcd.clear(); setupSDcard();//try to re-init the SD card...(this was failing, but a fix can be done below) //In the SD.CPP in the BEGIN class which starts // boolean SDClass::begin(uint8_t csPin) { // //it needs the line below to be added // // if (root.isOpen()) root.close(); // allows repeated calls // // Just before the line // return card.init(SPI_HALF_SPEED, csPin) && // // return; } DisplayCurrentFilename(); } void DisplayCurrentFilename() { m_CurrentFilename = m_FileNames[m_FileIndex]; lcd.clear(); lcd.print(m_CurrentFilename); } void GetFileNamesFromSD(File dir) { int fileCount = 0; String CurrentFilename = ""; while(1) { File entry = dir.openNextFile(); if (! entry) { // no more files m_NumberOfFiles = fileCount; break; } else { if (entry.isDirectory()) { //GetNextFileName(root); } else { CurrentFilename = entry.name(); if (CurrentFilename.endsWith(".bmp") || CurrentFilename.endsWith(".BMP") )//find files with our extension only { m_FileNames[fileCount] = entry.name(); fileCount++; } } } } } void latchanddelay(int dur) { strip.show(); delay(dur); } void ClearStrip(int duration) { int x; for(x=0;x STRIP_LENGTH) { displayWidth = STRIP_LENGTH;//only display the number of led's we have } /* compute the line length */ uint32_t lineLength = imgWidth * 3; if ((lineLength % 4) != 0) lineLength = (lineLength / 4 + 1) * 4; Serial.println("Line Length"); Serial.println(lineLength,DEC); int x = 0; for(int y=imgHeight;y>0 ;y--) { int bufpos=0; for(int x=0;x = 0) && (j < filenames[k]); k--) { filenames[k + 1] = filenames[k]; } filenames[k + 1] = j; } }