Advertisement
Guest User

Digital Light Wand + LCD + SD + LPD8806 + BMP direct + fixes

a guest
Nov 11th, 2012
1,200
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 12.24 KB | None | 0 0
  1. //
  2. // Arduino Digital Light Wand + SD + LCD V1.04A (LPD8806)
  3. // by Is0-Mick 2012
  4. //
  5. //This version supports direct reading of a 24bit BMP from the SD card.
  6. //You need to rotate the image 90 degrees right, due to lack of memory / speed to process
  7. //this on the fly...
  8. //
  9. //
  10. // Fixed a strange problem with 1 green pixel being left on if the last line of the image
  11. // or last pixel was not black. Apparently seems to be a known hardware / library bug...
  12. //
  13. // Tidied up code
  14. //
  15. // Fixed Backlight Problem
  16. //
  17. // Fixed the SD init problem (removing card, trying to send a file (which fails) now re-inits the card.
  18. // Backlight now fades out, instead of just switching off.
  19. //
  20. // Changed one of the original values of the shields key values, as it was thinking you were pressing a different
  21. // button sometimes, so changed the 535 value to 600 which seems to fix that :)
  22. //
  23. // Added code for an external switch to show the bitmap so you don't have fiddle with the small button on the shield
  24. // Pins are defined as aux button. I pulled one low as a GND, and the other is the trigger.(pins 44,45 currently)
  25.  
  26.  
  27.  
  28.  
  29. #include <LPD8806.h>
  30. #include <SD.h>
  31. #include <LiquidCrystal.h>
  32. #include <SPI.h>
  33.  
  34.  
  35. #define BACKLIGHT 10
  36. #define SDssPin 53  //SD card CS pin
  37. int frameDelay = 10; // default for the frame delay
  38. LiquidCrystal lcd(8, 9, 4, 5, 6, 7);  //Init the LCD
  39.  
  40. int dataPin = 31;
  41. int clockPin = 32;
  42.  
  43. #define STRIP_LENGTH 52
  44.  
  45. LPD8806 strip = LPD8806(STRIP_LENGTH, dataPin, clockPin);
  46.  
  47. //BacklightControl to save battery Life
  48. boolean BackLightTimer = false;
  49. int BackLightTimeout = 2000;
  50. int BackLightTemp =  BackLightTimeout;
  51.  
  52. //Stuff for the Keypad
  53. //int adc_key_val[5] ={
  54. //  30, 150, 360, 535, 760 };
  55.  
  56. int adc_key_val[5] ={
  57.   30, 150, 360, 600, 760 };  
  58. int NUM_KEYS = 5;
  59. int adc_key_in;
  60. int key=-1;
  61. int oldkey=-1;
  62.  
  63. //AuxButton is a seperate button to send the image. Connect wires to these pins to use it.
  64. int AuxButton = 44;
  65. int AuxButtonGND = 45;
  66.  
  67. File root;
  68. File dataFile;
  69. String m_CurrentFilename = "";
  70. int m_FileIndex = 0;
  71. int m_NumberOfFiles = 0;
  72. String m_FileNames[200]; //yep this is bad, but unless you are going to have over 200 images on your lightwand..
  73.  
  74. long buffer[STRIP_LENGTH];
  75.  
  76. void setup()
  77. {
  78.   Serial.begin(115200);
  79.   pinMode(AuxButton, INPUT);
  80.   digitalWrite(AuxButton,HIGH);
  81.   pinMode(AuxButtonGND, OUTPUT);
  82.   digitalWrite(AuxButtonGND,LOW);
  83.   setupLEDs();
  84.   setupLCDdisplay();
  85.   setupSDcard();
  86.   BackLightOn();
  87. }
  88.  
  89. void setupLEDs()
  90. {
  91.   strip.begin();
  92.   strip.show();
  93. }
  94.  
  95. void setupLCDdisplay()
  96. {
  97.   lcd.begin(16,2);
  98.   lcd.print("  *** DLW ***");
  99.   lcd.setCursor(0, 1);
  100.   lcd.print("Initializing...");
  101.   delay(1000);  
  102.   lcd.clear();
  103. }
  104.  
  105. void setupSDcard()
  106. {
  107.   pinMode(SDssPin, OUTPUT);
  108.  
  109.   while (!SD.begin(SDssPin)) {
  110.     BackLightOn();
  111.     lcd.print("SD init failed!");
  112.     delay(1000);
  113.     lcd.clear();
  114.     delay(500);
  115.   }
  116.   lcd.clear();
  117.   lcd.print("SD init done.");
  118.   delay(1000);
  119.   root = SD.open("/");
  120.   lcd.clear();
  121.   lcd.print("Scanning files");
  122.   delay(500);
  123.   GetFileNamesFromSD(root);
  124.   isort(m_FileNames, m_NumberOfFiles);
  125.   m_CurrentFilename = m_FileNames[0];
  126.   DisplayCurrentFilename();
  127.  
  128. }
  129.  
  130. int ReadKeypad()
  131. {
  132.   adc_key_in = analogRead(0);    // read the value from the sensor  
  133.   digitalWrite(13, HIGH);  
  134.   key = get_key(adc_key_in);                // convert into key press
  135.   Serial.print("key read = ");
  136.   Serial.println(adc_key_in,DEC);
  137.  
  138.   if (key != oldkey)                    // if keypress is detected
  139.   {
  140.     delay(50);      // wait for debounce time
  141.     adc_key_in = analogRead(0);    // read the value from the sensor  
  142.     key = get_key(adc_key_in);              // convert into key press
  143.     if (key != oldkey)             
  144.     {          
  145.       oldkey = key;
  146.       if (key >=0){
  147.         return key;
  148.       }
  149.     }
  150.   }
  151.   return key;
  152. }
  153.  
  154.  
  155. // Convert ADC value to key number
  156. int get_key(unsigned int input)
  157. {
  158.   int k;
  159.   for (k = 0; k < NUM_KEYS; k++)
  160.   {
  161.     if (input < adc_key_val[k])
  162.     {        
  163.       return k;
  164.     }
  165.   }
  166.   if (k >= NUM_KEYS)
  167.     k = -1;     // No valid key pressed
  168.   return k;
  169. }
  170.  
  171.  
  172. //The Main menu starts here...
  173. void loop()
  174. {
  175.   int keypress = ReadKeypad();
  176.   if ( keypress == 1) //up key (step up through the filenames)
  177.   {
  178.     BackLightOn();
  179.     if (m_FileIndex > 0)
  180.     {
  181.       m_FileIndex--;
  182.     }
  183.     else
  184.     {
  185.       m_FileIndex = m_NumberOfFiles -1; //wrap round to the last file
  186.     }
  187.  
  188.     DisplayCurrentFilename();
  189.     delay(500);
  190.   }
  191.  
  192.   if ( keypress == 2) //down key (step down through the filenames)
  193.   {
  194.     BackLightOn();
  195.     if (m_FileIndex < m_NumberOfFiles -1)
  196.     {
  197.       m_FileIndex++;
  198.     }
  199.     else
  200.     {
  201.       m_FileIndex = 0;//wrap round to the 1st file again
  202.     }
  203.     DisplayCurrentFilename();
  204.     delay(500);
  205.   }
  206.   //Serial.print(digitalRead(AuxButton),DEC);//for displaying the key values
  207.  
  208.   if ((keypress == 4) || (digitalRead(AuxButton) == LOW))//select key (send out the selected file)
  209.   {
  210.     SendFile(m_CurrentFilename);
  211.   }
  212.  
  213.   if(keypress == 0) //right key (frame delay +)
  214.   {
  215.     BackLightOn();
  216.     if (frameDelay < 200)
  217.     {
  218.       frameDelay+=5;
  219.     }
  220.     ShowFrameDelay();
  221.   }
  222.  
  223.   if(keypress == 3)//left key (frame delay -)
  224.   {
  225.     BackLightOn();
  226.     if (frameDelay > 5)
  227.     {
  228.       frameDelay-=5;
  229.     }
  230.     ShowFrameDelay();
  231.   }
  232.  
  233.   if (BackLightTimer == true) BackLightTime();
  234.  
  235. }
  236.  
  237. void BackLightOn()
  238. {
  239.   analogWrite(BACKLIGHT,255);
  240.   BackLightTimer = true;
  241.   BackLightTemp =  BackLightTimeout;
  242. }
  243.  
  244. void BackLightTime()
  245. {
  246.   if ((BackLightTemp <= 255) && (BackLightTemp >= 0))
  247.   {
  248.     analogWrite(BACKLIGHT,BackLightTemp);
  249.     delay(1);
  250.   }
  251.  
  252.   if (BackLightTemp <= 0)
  253.   {
  254.     BackLightTimer = false;
  255.     BackLightTemp =  BackLightTimeout;
  256.     analogWrite(BACKLIGHT,0);
  257.   }
  258.   else
  259.   {
  260.     BackLightTemp --;
  261.     delay(1);
  262.   }
  263. }
  264.  
  265. void ShowFrameDelay()
  266. {
  267.   lcd.clear();
  268.   lcd.print("Frame delay:");
  269.   lcd.setCursor(0,1);
  270.   lcd.print(frameDelay);
  271.   delay(500);
  272.   DisplayCurrentFilename();
  273. }
  274.  
  275.  
  276. void SendFile(String Filename)
  277. {
  278.   lcd.clear();
  279.   lcd.print("Sending File");
  280.   lcd.setCursor(0, 1);
  281.   lcd.print(Filename);
  282.   char temp[14];
  283.   Filename.toCharArray(temp,14);
  284.  
  285.   dataFile = SD.open(temp);
  286.  
  287.   // if the file is available send it to the LED's
  288.   if (dataFile)
  289.   {
  290.     ReadTheFile();
  291.     dataFile.close();
  292.     ClearStrip(100);
  293.   }  
  294.   else
  295.   {
  296.     lcd.clear();
  297.     lcd.print("  Error reading");
  298.     lcd.setCursor(4, 1);
  299.     lcd.print("file");
  300.     BackLightOn();
  301.     delay(1000);
  302.     lcd.clear();
  303.     setupSDcard();//try to re-init the SD card...(this was failing, but a fix can be done below)
  304.     //In the SD.CPP in the BEGIN class which starts
  305.     // boolean SDClass::begin(uint8_t csPin) {
  306.     //
  307.     //it needs the line below to be added
  308.     //
  309.     // if (root.isOpen()) root.close(); // allows repeated calls
  310.     //
  311.     // Just before the line
  312.     // return card.init(SPI_HALF_SPEED, csPin) &&
  313.     //
  314.     //
  315.  
  316.  
  317.     return;
  318.   }
  319.   DisplayCurrentFilename();
  320. }
  321.  
  322. void DisplayCurrentFilename()
  323. {
  324.   m_CurrentFilename = m_FileNames[m_FileIndex];
  325.   lcd.clear();
  326.   lcd.print(m_CurrentFilename);
  327. }
  328.  
  329. void GetFileNamesFromSD(File dir)
  330. {
  331.   int fileCount = 0;
  332.   String CurrentFilename = "";
  333.   while(1)
  334.   {
  335.     File entry =  dir.openNextFile();
  336.     if (! entry) {
  337.       // no more files
  338.       m_NumberOfFiles = fileCount;
  339.       break;
  340.     }
  341.     else
  342.     {
  343.       if (entry.isDirectory()) {
  344.         //GetNextFileName(root);
  345.       }
  346.       else {
  347.         CurrentFilename = entry.name();
  348.         if (CurrentFilename.endsWith(".bmp") || CurrentFilename.endsWith(".BMP") )//find files with our extension only
  349.         {
  350.           m_FileNames[fileCount] = entry.name();
  351.           fileCount++;
  352.         }
  353.       }
  354.     }
  355.   }
  356. }
  357.  
  358.  
  359. void latchanddelay(int dur)
  360. {
  361.   strip.show();
  362.   delay(dur);
  363. }
  364.  
  365. void ClearStrip(int duration)
  366. {
  367.   int x;
  368.   for(x=0;x<STRIP_LENGTH;x++)
  369.   {
  370.     strip.setPixelColor(x, 0);
  371.   }
  372.   strip.show();// Had to add this extra show, otherwise if you were displaying an image
  373.                // and the last line / pixel were white, a green pixel would remain lit!
  374.   latchanddelay(duration);
  375.  
  376. }
  377.  
  378. uint32_t readLong()
  379. {
  380.   uint32_t retValue;
  381.   byte incomingbyte;
  382.  
  383.   incomingbyte=readByte();
  384.   retValue=(uint32_t)((byte)incomingbyte);
  385.  
  386.   incomingbyte=readByte();
  387.   retValue+=(uint32_t)((byte)incomingbyte)<<8;
  388.  
  389.   incomingbyte=readByte();
  390.   retValue+=(uint32_t)((byte)incomingbyte)<<16;
  391.  
  392.   incomingbyte=readByte();
  393.   retValue+=(uint32_t)((byte)incomingbyte)<<24;
  394.  
  395.   return retValue;
  396. }
  397.  
  398. uint16_t readInt()
  399. {
  400.   byte incomingbyte;
  401.   uint16_t retValue;
  402.  
  403.   incomingbyte=readByte();
  404.   retValue+=(uint16_t)((byte)incomingbyte);
  405.  
  406.   incomingbyte=readByte();
  407.   retValue+=(uint16_t)((byte)incomingbyte)<<8;
  408.  
  409.   return retValue;
  410. }
  411.  
  412. int readByte()
  413. {
  414.   int retbyte=-1;
  415.   while(retbyte<0) retbyte= dataFile.read();
  416.   return retbyte;
  417. }
  418.  
  419.  
  420. void ReadTheFile()
  421. {
  422. #define MYBMP_BF_TYPE           0x4D42
  423. #define MYBMP_BF_OFF_BITS       54
  424. #define MYBMP_BI_SIZE           40
  425. #define MYBMP_BI_RGB            0L
  426. #define MYBMP_BI_RLE8           1L
  427. #define MYBMP_BI_RLE4           2L
  428. #define MYBMP_BI_BITFIELDS      3L
  429.  
  430.  
  431.  
  432.   uint16_t bmpType = readInt();
  433.   uint32_t bmpSize = readLong();
  434.   uint16_t bmpReserved1 = readInt();
  435.   uint16_t bmpReserved2 = readInt();
  436.   uint32_t bmpOffBits = readLong();
  437.   bmpOffBits = 54;
  438.  
  439.   Serial.println("bmpType = ");
  440.   Serial.println(bmpType,HEX);
  441.  
  442.   Serial.println("bmpSize");
  443.   Serial.println(bmpSize,DEC);
  444.  
  445.   Serial.println("bmpReserved1");
  446.   Serial.println(bmpReserved1,DEC);
  447.  
  448.   Serial.println("bmpReserved2");
  449.   Serial.println(bmpReserved2,DEC);
  450.  
  451.  
  452.   Serial.println("bmpOffBits");
  453.   Serial.println(bmpOffBits,DEC);
  454.  
  455.   /* Check file header */
  456.   if (bmpType != MYBMP_BF_TYPE || bmpOffBits != MYBMP_BF_OFF_BITS)
  457.   {
  458.     lcd.setCursor(0, 0);
  459.     lcd.print("not a bitmap");
  460.     delay(1000);
  461.     return;
  462.   }
  463.  
  464.   /* Read info header */
  465.   uint32_t imgSize = readLong();
  466.   uint32_t imgWidth = readLong();
  467.   uint32_t imgHeight = readLong();
  468.   uint16_t imgPlanes = readInt();
  469.   uint16_t imgBitCount = readInt();
  470.   uint32_t imgCompression = readLong();
  471.   uint32_t imgSizeImage = readLong();
  472.   uint32_t imgXPelsPerMeter = readLong();
  473.   uint32_t imgYPelsPerMeter = readLong();
  474.   uint32_t imgClrUsed = readLong();
  475.   uint32_t imgClrImportant = readLong();
  476.  
  477.  
  478.   Serial.println("bitmap height");
  479.   Serial.println(imgHeight,DEC);
  480.   Serial.println("bitmap Width");
  481.   Serial.println(imgWidth,DEC);
  482.   Serial.println("bitmap bpp");
  483.   Serial.println(imgBitCount,DEC);
  484.  
  485.   /* Check info header */
  486.   if( imgSize != MYBMP_BI_SIZE || imgWidth <= 0 ||
  487.     imgHeight <= 0 || imgPlanes != 1 ||
  488.     imgBitCount != 24 || imgCompression != MYBMP_BI_RGB ||
  489.     imgSizeImage == 0 )
  490.   {
  491.     lcd.setCursor(0, 0);
  492.     lcd.print("Unsupported");
  493.     lcd.setCursor(0, 1);
  494.     lcd.print("Bitmap Use 24bpp");
  495.     delay(1000);
  496.     return;
  497.   }
  498.  
  499.   int displayWidth = imgWidth;
  500.   if (imgWidth > STRIP_LENGTH)
  501.   {
  502.     displayWidth = STRIP_LENGTH;//only display the number of led's we have
  503.   }
  504.  
  505.  
  506.   /* compute the line length */
  507.   uint32_t lineLength = imgWidth * 3;
  508.   if ((lineLength % 4) != 0)
  509.     lineLength = (lineLength / 4 + 1) * 4;
  510.  
  511.   Serial.println("Line Length");
  512.   Serial.println(lineLength,DEC);
  513.  
  514.   int x = 0;
  515.   for(int y=imgHeight;y>0 ;y--) {
  516.  
  517.     int bufpos=0;    
  518.     for(int x=0;x <displayWidth  ;x++) {
  519.  
  520.       uint32_t offset = (MYBMP_BF_OFF_BITS + (((y-1)* lineLength) + (x*3))) ;
  521.  
  522.       /*
  523.       Serial.println("offset");
  524.        Serial.println(offset,HEX);
  525.        Serial.println("X = ");
  526.        Serial.println(x,DEC);
  527.        Serial.println("Y = ");
  528.        Serial.println(y,DEC);
  529.        */
  530.  
  531.     dataFile.seek(offset);
  532.  
  533.     int g=((readByte() & 0xff)>>1);
  534.     int b=((readByte() & 0xff)>>1);
  535.     int r=((readByte() & 0xff)>>1);
  536.     strip.setPixelColor(x,r,g,b);
  537.     }
  538.     latchanddelay(frameDelay);
  539.  
  540.   }
  541.   Serial.println("Finished");
  542.   ClearStrip(100);
  543. }
  544.  
  545. //sort the filenames in alphabetical order
  546. void isort(String *filenames, int n)
  547. {
  548.   for (int i = 1; i < n; ++i)
  549.   {
  550.     String j = filenames[i];
  551.     int k;
  552.     for (k = i - 1; (k >= 0) && (j < filenames[k]); k--)
  553.     {
  554.       filenames[k + 1] = filenames[k];
  555.     }
  556.     filenames[k + 1] = j;
  557.   }
  558. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement