Ebay Cheapies 001
A couple of my ebay cheap buys have arrived. I have an Arduino Mega for $12, and a 8×8 LED Matrix with a (fake) MAX7219 driver for $3. To test them out, i’ve hooked them both up, and wrote some Arduino code to show what they can do.
I usually don’t use Arduino for Projects, but for testing out some parts it works great! Don’t even have to get my MKII programmer out fo the drawer.
Also as a bonus, my knock off Saleae Logic Anayzler ($10) has arrived. I’ve used it to plot out the logic of shifting the data from the Arduino to the MAX7219.
Not much else to say here, so lets get into some pictures, code, and a video!
MAX7219 kit: Pretty simple setup here, the MAX7219 provides 3 data lines to the arduino, which allows the 8×8 matrix to set which leds are to be lit.
Arduino Mega: The back and front of the Arduino Mega. Amazing value at $10, considering the retail price of the non-clone is like $70. The only difference i could tell is the back of the PCB looks to say ‘ROARD’ instead of ‘BOARD’.
‘Saleae’ Logic Anazlyer: A $10 rip off of the Saleae system. Looks nothing like the quite refined Saleae logic, but does the job quite well. Uses the official software form Saleae. Read somewhere that this can be reconfigured to use the USBee software also, but havn’t had a chance to look at that yet.
Here is a screen shot showing the analyzer in use, channel description:
- MAX7219 Clock line
- MAX7219 Load line
- MAX7219 Data line
- Custom line to show pushing out an entire 8×8 led update
Here is the video showing a quick demostration of using the MAX7219 kit and the Arduino Mega
And finally, the code for doing this. The MAX7219 code has been ripped from the arduino.cc website. The rotary code is my own, which you can read more about in this post here. This will also work on a standard Arduino (clones available on the net form $8!)
You can also find the lastest version of this code on my SVN repo here.
** RECOMMEND using the above WebSVN link until i sort out my Syntax Highligter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 | #include <Encoder.h> // Delays for certain events in ms const int ROTARY_DELAY = 100; // Time between checking for rotary turns const int BUTTON_DELAY = 800; // Button debouncing, and repeating const int FLASH_DELAY = 600; // How long to flash the entire row after button press const int CURSOR_DELAY = 200; // How quickly to flash the cursor led // Pin Assignments uint8_t rota = 2; uint8_t rotb = 3; uint8_t button = 4; uint8_t dataIn = 5; uint8_t load = 6; uint8_t clock = 7; uint8_t trigger = 12; int maxInUse = 1; uint8_t x = 0; byte max7219_reg_noop = 0x00; byte max7219_reg_digit0 = 0x01; byte max7219_reg_digit1 = 0x02; byte max7219_reg_digit2 = 0x03; byte max7219_reg_digit3 = 0x04; byte max7219_reg_digit4 = 0x05; byte max7219_reg_digit5 = 0x06; byte max7219_reg_digit6 = 0x07; byte max7219_reg_digit7 = 0x08; byte max7219_reg_decodeMode = 0x09; byte max7219_reg_intensity = 0x0a; byte max7219_reg_scanLimit = 0x0b; byte max7219_reg_shutdown = 0x0c; byte max7219_reg_displayTest = 0x0f; Encoder knobLeft(rota, rotb); char id=0; void putByte(byte data) { byte i = 8; byte mask; while(i > 0) { mask = 0x01 << (i - 1); // get bitmask digitalWrite( clock, LOW); // tick if (data & mask){ // choose bit digitalWrite(dataIn, HIGH);// send 1 }else{ digitalWrite(dataIn, LOW); // send 0 } digitalWrite(clock, HIGH); // tock --i; // move to lesser bit } } void maxSingle( byte reg, byte col) { //maxSingle is the "easy" function to use for a //single max7219 digitalWrite(load, LOW); // begin putByte(reg); // specify register putByte(col);//((data & 0x01) * 256) + data >> 1); // put data digitalWrite(load, LOW); // and load da shit digitalWrite(load,HIGH); } void maxAll (byte reg, byte col) { // initialize all MAX7219's in the system int c = 0; digitalWrite(load, LOW); // begin for ( c =1; c<= maxInUse; c++) { putByte(reg); // specify register putByte(col);//((data & 0x01) * 256) + data >> 1); // put data } digitalWrite(load, LOW); digitalWrite(load,HIGH); } void maxOne(byte maxNr, byte reg, byte col) { //maxOne is for adressing different MAX7219's, //whilele having a couple of them cascaded int c = 0; digitalWrite(load, LOW); // begin for ( c = maxInUse; c > maxNr; c--) { putByte(0); // means no operation putByte(0); // means no operation } putByte(reg); // specify register putByte(col);//((data & 0x01) * 256) + data >> 1); // put data for ( c =maxNr-1; c >= 1; c--) { putByte(0); // means no operation putByte(0); // means no operation } digitalWrite(load, LOW); // and load da shit digitalWrite(load,HIGH); } void setup () { pinMode(dataIn, OUTPUT); pinMode(clock, OUTPUT); pinMode(load, OUTPUT); pinMode(button, INPUT); pinMode(trigger, OUTPUT); digitalWrite(button, HIGH); digitalWrite(13, LOW); digitalWrite(trigger, LOW); //initiation of the max 7219 maxAll(max7219_reg_scanLimit, 0x07); maxAll(max7219_reg_decodeMode, 0x00); // using an led matrix (not digits) maxAll(max7219_reg_shutdown, 0x01); // not in shutdown mode maxAll(max7219_reg_displayTest, 0x00); // no display test for (x=1; x<=8; x++) { // empty registers, turn all LEDs off maxAll(x,0); } maxAll(max7219_reg_intensity, 0x01 & 0x0f); // the first 0x0f is the value you can set range: 0x00 to 0x0f } // Value to display a single LED on a row uint8_t values[9] = {0, 1, 2, 4, 8, 16, 32, 64, 128}; // Array with all rows, indicating which 'value' to show uint8_t line[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // What row we are current working with uint8_t idx = 0; // Our delay counters (in ms) int delayButton = 0; int delayRotary = ROTARY_DELAY; int delayFlash = 0; int delayCursor = CURSOR_DELAY; int cursorState = 0; // Rotary position, reset after each loop long pos = 0; // Do we update the matrix this run? uint8_t update = 1; void loop () { // Flash the row after a button press if (delayFlash && idx != 8) { maxSingle(idx+1, 255); if (delayFlash == 1) { maxSingle(idx+1, values[line[idx+1]]); } delayFlash--; if (delayButton) delayButton--; return; } // Check for button press if (delayButton) delayButton--; if (!digitalRead(4) && delayButton == 0) { if (idx == 8) idx = 0; else idx++; delayButton = BUTTON_DELAY; delayFlash = FLASH_DELAY; } // Checks for rotary turning, and update // the matrix buffer // My rotary encoder had '2 turns' per detent, making // it awkward to move a single position. This is why // the check is for > 1 and < -1 to make it a full detent. if (delayRotary) delayRotary--; if (delayRotary == 0 && idx != 8) { pos = knobLeft.read(); if (pos > 1) { if (line[idx] != 0) line[idx]--; else line[idx] = 8; update = 1; } else if (pos < -1) { if (line[idx] != 8) line[idx]++; else line[idx]= 0; update = 1; } if (update) { knobLeft.write(0); delayRotary = ROTARY_DELAY; if (pos) { cursorState = 1; delayCursor = CURSOR_DELAY; } } } // Toggle the state of the cursor after the // cursor delay (in ms) has been reached if (delayCursor) delayCursor--; if (delayCursor == 0 && idx != 8) { delayCursor = CURSOR_DELAY; cursorState = 1 - cursorState; update = 1; } // Update the matrix only if a change has been made if (update) { for (x = 0; x<8; x++) { if (x == idx) { if (cursorState && line[x] != 0) maxSingle(x+1, values[line[x]]); else maxSingle(x+1, 0); } else { if (line[x] == 0) continue; digitalWrite(trigger, HIGH); maxSingle(x+1, values[line[x]]); digitalWrite(trigger, LOW); } } update = 0; } delay(1); } |