Components and supplies
LED (generic)
Resistor 1M ohm
Female Header 8 Position 1 Row (0.1")
Arduino Nano R3
IC & Component Socket, 8 Contacts
Apps and platforms
Arduino IDE
Project description
Code
Arduino sketch
arduino
Software implementation, Arduino IDE.
1/* 2 * Program for Ironman logo 3 * By: JJ 4 */ 5 6#include <Wire.h> 7 8unsigned char button_id = 12; 9bool button_press = true; 10unsigned long int debouncer = 0; 11char pattern_num = 5; 12 13int alternateFlag = 0; 14 15unsigned char pattern_buffer[32][32]; 16unsigned char ledstate[38]; 17unsigned char sawtooth_poly[32]; 18unsigned int pwm_pin_nums[6]; 19unsigned char sawtooth = 0; 20unsigned long int triangle = 0; 21bool triangle_up = true; 22 23char buffer_index = 0; 24 25unsigned long int timeTracker; 26 27// the setup function runs once when you press reset or power the board 28void setup() { 29 30 // Polynomial delinearization via the following formula 31 // ((x^0.5) * 32^0.5) + 1 32 // This will allow us to linearize the apparent brightness of the LEDs 33 // We will use a lookup table to improve runtime efficiency 34 float sqrt_32 = sqrt(32); 35 for (int i = 0; i < 32; i++) 36 { 37 //sawtooth_poly[i] = ( i * i / 32 ) + 1; 38 sawtooth_poly[i] = (sqrt(i) * sqrt_32 + 1) * 8; 39 } 40 41 for (int i = 0; i < 38; i++) 42 { 43 ledstate[i] = 0; 44 } 45 46 int ledPin1 = 3; 47 int ledPin2 = 5; 48 int ledPin3 = 6; 49 int ledPin4 = 9; 50 int ledPin5 = 10; 51 int ledPin6 = 11; 52 53 pwm_pin_nums[0] = ledPin1; 54 pwm_pin_nums[1] = ledPin2; 55 pwm_pin_nums[2] = ledPin3; 56 pwm_pin_nums[3] = ledPin4; 57 pwm_pin_nums[4] = ledPin5; 58 pwm_pin_nums[5] = ledPin6; 59 60 61 // initialize digital pins as outputs 62 pinMode(ledPin1, OUTPUT); 63 pinMode(ledPin2, OUTPUT); 64 pinMode(ledPin3, OUTPUT); 65 pinMode(ledPin4, OUTPUT); 66 pinMode(ledPin5, OUTPUT); 67 pinMode(ledPin6, OUTPUT); 68 69 pinMode(button_id, INPUT_PULLUP); 70 71 //timeTracker = millis(); 72 73 // Open up the floodgates of I2C 74 Wire.begin(); // join i2c bus (address optional for master) 75 76 // Change the I2C clock rate from 100k to 400k by knocking the TWBR value down from 72 to 18 77 TWBR = 18; 78 79 Wire.beginTransmission(0x20); // Select the first chip 80 Wire.write(0x06); // Enter command to configure this bubby 81 Wire.write(0x00); // Enable outputs on P0 82 Wire.write(0x00); // Enable outputs on P1 83 Wire.endTransmission(); // Finish up the transaction 84 85 Wire.beginTransmission(0x21); // Select the first chip 86 Wire.write(0x06); // Enter command to configure this bubby 87 Wire.write(0x00); // Enable outputs on P0 88 Wire.write(0x00); // Enable outputs on P1 89 Wire.endTransmission(); // Finish up the transaction 90} 91 92// the loop function runs over and over again forever 93void loop() 94{ 95 if (button_press) 96 { 97 buffer_index = 0; 98 button_press = false; 99 generate_new_pattern(); 100 } 101 102 // If we got a button press, do some rudimentary debouncing and set a flag for later 103 if (!digitalRead(button_id)) 104 { 105 if (debouncer < millis() && !button_press) 106 { 107 debouncer = millis() + 1000; 108 button_press = true; 109 } 110 } 111 calculate_values(); 112 113 write_values(); 114} 115 116void generate_new_pattern() 117{ 118 switch (++pattern_num) 119 { 120 case 1: 121 for (int led_iter = 0; led_iter < 32; led_iter++) 122 { 123 for (int buffer_iter = 0; buffer_iter < 32; buffer_iter++) 124 { 125 pattern_buffer[led_iter][buffer_iter] = max( ( (32 - ((led_iter + buffer_iter) % 32)) << 3) - 64, 0); 126 } 127 } 128 break; 129 case 2: 130 for (int led_iter = 0; led_iter < 32; led_iter++) 131 { 132 for (int buffer_iter = 0; buffer_iter < 32; buffer_iter++) 133 { 134 pattern_buffer[led_iter][buffer_iter] = max((abs(16 - buffer_iter) << 3) - 33, 0); ; 135 } 136 } 137 break; 138 case 3: 139 for (int led_iter = 0; led_iter < 32; led_iter++) 140 { 141 for (int buffer_iter = 0; buffer_iter < 32; buffer_iter++) 142 { 143 if (buffer_iter == 0) pattern_buffer[led_iter][buffer_iter] = (rand() % 50) + 15; 144 else pattern_buffer[led_iter][buffer_iter] = min(max(pattern_buffer[led_iter][buffer_iter - 1] + ((rand() % 3) - 1) * 10, 0), 255); 145 } 146 } 147 break; 148 case 4: 149 for (int led_iter = 0; led_iter < 32; led_iter++) 150 { 151 for (int buffer_iter = 0; buffer_iter < 32; buffer_iter++) 152 { 153 pattern_buffer[led_iter][buffer_iter] = max( (((led_iter % 16 + (32 - buffer_iter)) % 16) << 5) - 256, 0); 154 } 155 } 156 break; 157 case 5: 158 for (int led_iter = 0; led_iter < 32; led_iter++) 159 { 160 int peaks = 3; 161 for (int buffer_iter = 0; buffer_iter < 32; buffer_iter++) 162 { 163 pattern_buffer[led_iter][buffer_iter] = min(max(300 * (sin(2 * PI * peaks * (buffer_iter + led_iter) / 32.0) + 1) - 400, 0), 255); 164 } 165 } 166 break; 167 case 6: 168 for (int led_iter = 0; led_iter < 32; led_iter++) 169 { 170 // Left to right. Convert LED number into an angle (radians) 171 float led_pos_x = cos(((led_iter - 8) % 32) / 32.0 * 2 * PI); 172 float led_pos_y = sin(((led_iter - 8) % 32) / 32.0 * 2 * PI); 173 float led_pos_xn = cos(((led_iter + 8) % 32) / 32.0 * 2 * PI); 174 float led_pos_yn = sin(((led_iter + 8) % 32) / 32.0 * 2 * PI); 175 float width = 0.2; 176 for (int buffer_iter = 0; buffer_iter < 32; buffer_iter++) 177 { 178 // Convert our buffer position into a horizontal displacement 179 float buffer_pos = (buffer_iter % 8) / 3.0 - 1.25; 180 181 if (buffer_iter < 8) 182 { 183 float horiz_dist = abs(buffer_pos - led_pos_x); 184 185 if (horiz_dist < width) 186 { 187 pattern_buffer[led_iter][buffer_iter] = (width - horiz_dist) / width * 255; 188 } 189 else 190 { 191 pattern_buffer[led_iter][buffer_iter] = 0; 192 } 193 } 194 else if (buffer_iter < 16) 195 { 196 float vert_dist = abs(buffer_pos - led_pos_y); 197 198 if (vert_dist < width) 199 { 200 pattern_buffer[led_iter][buffer_iter] = (width - vert_dist) / width * 255; 201 } 202 else 203 { 204 pattern_buffer[led_iter][buffer_iter] = 0; 205 } 206 } 207 else if (buffer_iter < 24) 208 { 209 float horiz_dist = abs(buffer_pos - led_pos_xn); 210 211 if (horiz_dist < width) 212 { 213 pattern_buffer[led_iter][buffer_iter] = (width - horiz_dist) / width * 255; 214 } 215 else 216 { 217 pattern_buffer[led_iter][buffer_iter] = 0; 218 } 219 } 220 else 221 { 222 float vert_dist = abs(buffer_pos - led_pos_yn); 223 224 if (vert_dist < width) 225 { 226 pattern_buffer[led_iter][buffer_iter] = (width - vert_dist) / width * 255; 227 } 228 else 229 { 230 pattern_buffer[led_iter][buffer_iter] = 0; 231 } 232 } 233 234 } 235 } 236 break; 237 default: 238 for (int led_iter = 0; led_iter < 32; led_iter++) 239 { 240 for (int buffer_iter = 0; buffer_iter < 32; buffer_iter++) 241 { 242 unsigned char cw = max( ( (32 - ((led_iter + buffer_iter) % 32)) << 5) - 768, 0); 243 unsigned char ccw = max( ( (((led_iter + 32 - buffer_iter) % 32)) << 5) - 768, 0); 244 245 pattern_buffer[led_iter][buffer_iter] = max(cw, ccw); 246 } 247 } 248 pattern_num = 0; 249 break; 250 } 251} 252 253void calculate_values() 254{ 255 sawtooth += 8; 256 257 if (timeTracker <= millis()) 258 { 259 buffer_index++; 260 if (buffer_index >= 32) 261 { 262 buffer_index %= 32; 263 } 264 timeTracker += 50; 265 } 266 267 for (int i = 0; i < 32; i++) 268 { 269 ledstate[i] = pattern_buffer[i][buffer_index]; 270 } 271 272 for ( int i = 32; i < 38; i ++) 273 { 274 ledstate[i] = max((abs(16 - buffer_index) << 4) - 33, 0); 275 } 276} 277 278 279void write_values() 280{ 281 unsigned char byte1 = 0; 282 unsigned char byte2 = 0; 283 unsigned char byte3 = 0; 284 unsigned char byte4 = 0; 285 286 for (int iter = 0; iter < 8; iter++) 287 { 288 if (ledstate[iter] <= sawtooth_poly[sawtooth >> 3]) 289 { 290 byte1 = byte1 | (1 << (iter % 8)); 291 } 292 } 293 294 for (int iter = 8; iter < 16; iter++) 295 { 296 if (ledstate[iter] <= sawtooth_poly[sawtooth >> 3]) 297 { 298 byte2 = byte2 | (1 << (iter % 8)); 299 } 300 } 301 for (int iter = 16; iter < 24; iter++) 302 { 303 if (ledstate[iter] <= sawtooth_poly[sawtooth >> 3]) 304 { 305 byte3 = byte3 | (1 << (iter % 8)); 306 } 307 } 308 for (int iter = 24; iter < 32; iter++) 309 { 310 if (ledstate[iter] <= sawtooth_poly[sawtooth >> 3]) 311 { 312 byte4 = byte4 | (1 << (iter % 8)); 313 } 314 } 315 316 Wire.beginTransmission(0x20); // Select the first chip 317 Wire.write(0x02); // Enter command to configure this bubby 318 Wire.write(byte1); // Enable outputs on P0 319 Wire.write(byte2); // Enable outputs on P1 320 Wire.endTransmission(); // Finish up the transaction 321 322 Wire.beginTransmission(0x21); // Select the first chip 323 Wire.write(0x02); // Enter command to configure this bubby 324 Wire.write(byte3); // Enable outputs on P0 325 Wire.write(byte4); // Enable outputs on P1 326 Wire.endTransmission(); // Finish up the transaction 327 328 for (int i = 32; i < 38; i++) 329 { 330 analogWrite(pwm_pin_nums[i - 32], ledstate[i]); 331 } 332 333} 334 335 336
Arduino sketch
arduino
Software implementation, Arduino IDE.
1/* 2 * Program for Ironman logo 3 * By: JJ 4 */ 5 6#include <Wire.h> 7 8unsigned char button_id = 12; 9bool button_press = true; 10unsigned long int debouncer = 0; 11char pattern_num = 5; 12 13int alternateFlag = 0; 14 15unsigned char pattern_buffer[32][32]; 16unsigned char ledstate[38]; 17unsigned char sawtooth_poly[32]; 18unsigned int pwm_pin_nums[6]; 19unsigned char sawtooth = 0; 20unsigned long int triangle = 0; 21bool triangle_up = true; 22 23char buffer_index = 0; 24 25unsigned long int timeTracker; 26 27// the setup function runs once when you press reset or power the board 28void setup() { 29 30 // Polynomial delinearization via the following formula 31 // ((x^0.5) * 32^0.5) + 1 32 // This will allow us to linearize the apparent brightness of the LEDs 33 // We will use a lookup table to improve runtime efficiency 34 float sqrt_32 = sqrt(32); 35 for (int i = 0; i < 32; i++) 36 { 37 //sawtooth_poly[i] = ( i * i / 32 ) + 1; 38 sawtooth_poly[i] = (sqrt(i) * sqrt_32 + 1) * 8; 39 } 40 41 for (int i = 0; i < 38; i++) 42 { 43 ledstate[i] = 0; 44 } 45 46 int ledPin1 = 3; 47 int ledPin2 = 5; 48 int ledPin3 = 6; 49 int ledPin4 = 9; 50 int ledPin5 = 10; 51 int ledPin6 = 11; 52 53 pwm_pin_nums[0] = ledPin1; 54 pwm_pin_nums[1] = ledPin2; 55 pwm_pin_nums[2] = ledPin3; 56 pwm_pin_nums[3] = ledPin4; 57 pwm_pin_nums[4] = ledPin5; 58 pwm_pin_nums[5] = ledPin6; 59 60 61 // initialize digital pins as outputs 62 pinMode(ledPin1, OUTPUT); 63 pinMode(ledPin2, OUTPUT); 64 pinMode(ledPin3, OUTPUT); 65 pinMode(ledPin4, OUTPUT); 66 pinMode(ledPin5, OUTPUT); 67 pinMode(ledPin6, OUTPUT); 68 69 pinMode(button_id, INPUT_PULLUP); 70 71 //timeTracker = millis(); 72 73 // Open up the floodgates of I2C 74 Wire.begin(); // join i2c bus (address optional for master) 75 76 // Change the I2C clock rate from 100k to 400k by knocking the TWBR value down from 72 to 18 77 TWBR = 18; 78 79 Wire.beginTransmission(0x20); // Select the first chip 80 Wire.write(0x06); // Enter command to configure this bubby 81 Wire.write(0x00); // Enable outputs on P0 82 Wire.write(0x00); // Enable outputs on P1 83 Wire.endTransmission(); // Finish up the transaction 84 85 Wire.beginTransmission(0x21); // Select the first chip 86 Wire.write(0x06); // Enter command to configure this bubby 87 Wire.write(0x00); // Enable outputs on P0 88 Wire.write(0x00); // Enable outputs on P1 89 Wire.endTransmission(); // Finish up the transaction 90} 91 92// the loop function runs over and over again forever 93void loop() 94{ 95 if (button_press) 96 { 97 buffer_index = 0; 98 button_press = false; 99 generate_new_pattern(); 100 } 101 102 // If we got a button press, do some rudimentary debouncing and set a flag for later 103 if (!digitalRead(button_id)) 104 { 105 if (debouncer < millis() && !button_press) 106 { 107 debouncer = millis() + 1000; 108 button_press = true; 109 } 110 } 111 calculate_values(); 112 113 write_values(); 114} 115 116void generate_new_pattern() 117{ 118 switch (++pattern_num) 119 { 120 case 1: 121 for (int led_iter = 0; led_iter < 32; led_iter++) 122 { 123 for (int buffer_iter = 0; buffer_iter < 32; buffer_iter++) 124 { 125 pattern_buffer[led_iter][buffer_iter] = max( ( (32 - ((led_iter + buffer_iter) % 32)) << 3) - 64, 0); 126 } 127 } 128 break; 129 case 2: 130 for (int led_iter = 0; led_iter < 32; led_iter++) 131 { 132 for (int buffer_iter = 0; buffer_iter < 32; buffer_iter++) 133 { 134 pattern_buffer[led_iter][buffer_iter] = max((abs(16 - buffer_iter) << 3) - 33, 0); ; 135 } 136 } 137 break; 138 case 3: 139 for (int led_iter = 0; led_iter < 32; led_iter++) 140 { 141 for (int buffer_iter = 0; buffer_iter < 32; buffer_iter++) 142 { 143 if (buffer_iter == 0) pattern_buffer[led_iter][buffer_iter] = (rand() % 50) + 15; 144 else pattern_buffer[led_iter][buffer_iter] = min(max(pattern_buffer[led_iter][buffer_iter - 1] + ((rand() % 3) - 1) * 10, 0), 255); 145 } 146 } 147 break; 148 case 4: 149 for (int led_iter = 0; led_iter < 32; led_iter++) 150 { 151 for (int buffer_iter = 0; buffer_iter < 32; buffer_iter++) 152 { 153 pattern_buffer[led_iter][buffer_iter] = max( (((led_iter % 16 + (32 - buffer_iter)) % 16) << 5) - 256, 0); 154 } 155 } 156 break; 157 case 5: 158 for (int led_iter = 0; led_iter < 32; led_iter++) 159 { 160 int peaks = 3; 161 for (int buffer_iter = 0; buffer_iter < 32; buffer_iter++) 162 { 163 pattern_buffer[led_iter][buffer_iter] = min(max(300 * (sin(2 * PI * peaks * (buffer_iter + led_iter) / 32.0) + 1) - 400, 0), 255); 164 } 165 } 166 break; 167 case 6: 168 for (int led_iter = 0; led_iter < 32; led_iter++) 169 { 170 // Left to right. Convert LED number into an angle (radians) 171 float led_pos_x = cos(((led_iter - 8) % 32) / 32.0 * 2 * PI); 172 float led_pos_y = sin(((led_iter - 8) % 32) / 32.0 * 2 * PI); 173 float led_pos_xn = cos(((led_iter + 8) % 32) / 32.0 * 2 * PI); 174 float led_pos_yn = sin(((led_iter + 8) % 32) / 32.0 * 2 * PI); 175 float width = 0.2; 176 for (int buffer_iter = 0; buffer_iter < 32; buffer_iter++) 177 { 178 // Convert our buffer position into a horizontal displacement 179 float buffer_pos = (buffer_iter % 8) / 3.0 - 1.25; 180 181 if (buffer_iter < 8) 182 { 183 float horiz_dist = abs(buffer_pos - led_pos_x); 184 185 if (horiz_dist < width) 186 { 187 pattern_buffer[led_iter][buffer_iter] = (width - horiz_dist) / width * 255; 188 } 189 else 190 { 191 pattern_buffer[led_iter][buffer_iter] = 0; 192 } 193 } 194 else if (buffer_iter < 16) 195 { 196 float vert_dist = abs(buffer_pos - led_pos_y); 197 198 if (vert_dist < width) 199 { 200 pattern_buffer[led_iter][buffer_iter] = (width - vert_dist) / width * 255; 201 } 202 else 203 { 204 pattern_buffer[led_iter][buffer_iter] = 0; 205 } 206 } 207 else if (buffer_iter < 24) 208 { 209 float horiz_dist = abs(buffer_pos - led_pos_xn); 210 211 if (horiz_dist < width) 212 { 213 pattern_buffer[led_iter][buffer_iter] = (width - horiz_dist) / width * 255; 214 } 215 else 216 { 217 pattern_buffer[led_iter][buffer_iter] = 0; 218 } 219 } 220 else 221 { 222 float vert_dist = abs(buffer_pos - led_pos_yn); 223 224 if (vert_dist < width) 225 { 226 pattern_buffer[led_iter][buffer_iter] = (width - vert_dist) / width * 255; 227 } 228 else 229 { 230 pattern_buffer[led_iter][buffer_iter] = 0; 231 } 232 } 233 234 } 235 } 236 break; 237 default: 238 for (int led_iter = 0; led_iter < 32; led_iter++) 239 { 240 for (int buffer_iter = 0; buffer_iter < 32; buffer_iter++) 241 { 242 unsigned char cw = max( ( (32 - ((led_iter + buffer_iter) % 32)) << 5) - 768, 0); 243 unsigned char ccw = max( ( (((led_iter + 32 - buffer_iter) % 32)) << 5) - 768, 0); 244 245 pattern_buffer[led_iter][buffer_iter] = max(cw, ccw); 246 } 247 } 248 pattern_num = 0; 249 break; 250 } 251} 252 253void calculate_values() 254{ 255 sawtooth += 8; 256 257 if (timeTracker <= millis()) 258 { 259 buffer_index++; 260 if (buffer_index >= 32) 261 { 262 buffer_index %= 32; 263 } 264 timeTracker += 50; 265 } 266 267 for (int i = 0; i < 32; i++) 268 { 269 ledstate[i] = pattern_buffer[i][buffer_index]; 270 } 271 272 for ( int i = 32; i < 38; i ++) 273 { 274 ledstate[i] = max((abs(16 - buffer_index) << 4) - 33, 0); 275 } 276} 277 278 279void write_values() 280{ 281 unsigned char byte1 = 0; 282 unsigned char byte2 = 0; 283 unsigned char byte3 = 0; 284 unsigned char byte4 = 0; 285 286 for (int iter = 0; iter < 8; iter++) 287 { 288 if (ledstate[iter] <= sawtooth_poly[sawtooth >> 3]) 289 { 290 byte1 = byte1 | (1 << (iter % 8)); 291 } 292 } 293 294 for (int iter = 8; iter < 16; iter++) 295 { 296 if (ledstate[iter] <= sawtooth_poly[sawtooth >> 3]) 297 { 298 byte2 = byte2 | (1 << (iter % 8)); 299 } 300 } 301 for (int iter = 16; iter < 24; iter++) 302 { 303 if (ledstate[iter] <= sawtooth_poly[sawtooth >> 3]) 304 { 305 byte3 = byte3 | (1 << (iter % 8)); 306 } 307 } 308 for (int iter = 24; iter < 32; iter++) 309 { 310 if (ledstate[iter] <= sawtooth_poly[sawtooth >> 3]) 311 { 312 byte4 = byte4 | (1 << (iter % 8)); 313 } 314 } 315 316 Wire.beginTransmission(0x20); // Select the first chip 317 Wire.write(0x02); // Enter command to configure this bubby 318 Wire.write(byte1); // Enable outputs on P0 319 Wire.write(byte2); // Enable outputs on P1 320 Wire.endTransmission(); // Finish up the transaction 321 322 Wire.beginTransmission(0x21); // Select the first chip 323 Wire.write(0x02); // Enter command to configure this bubby 324 Wire.write(byte3); // Enable outputs on P0 325 Wire.write(byte4); // Enable outputs on P1 326 Wire.endTransmission(); // Finish up the transaction 327 328 for (int i = 32; i < 38; i++) 329 { 330 analogWrite(pwm_pin_nums[i - 32], ledstate[i]); 331 } 332 333} 334 335 336
Downloadable files
Schematic
Schematic and PCB data in attached zip. EagleCAD
Schematic
Comments
Only logged in users can leave comments