Components and supplies
Arduino UNO
DC Power Supply
transparent hose, 4mm diameter, 5m long
Saint Smart Motorshield
ArduiBox Enclosure
Tools and machines
Soldering iron (generic)
Project description
Code
Firmware
c_cpp
for Arduino Uno
1 2/* 3 * hose display for Maker Faire Hannover 2016 4 * Version 1.0 5 * Copyright (C) 2016 Hartmut Wendt www.hwhardsoft.de 6 * 7 * 8 * This program is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 20*/ 21 22#include <AFMotor.h> 23#include <font5x7.h> 24 25#define DEBOUNCE 10 // button debouncer, how many ms to debounce, 5+ ms is usually plenty 26 27// here is where we define the buttons that we'll use. button "1" is the first, button "6" is the 6th, etc 28byte buttons[] = {14, 15, 17, 18, 19}; // the analog 0-5 pins are also known as 14-19 29// This handy macro lets us determine how big the array up above is, by checking the size 30#define NUMBUTTONS sizeof(buttons) 31// we will track if a button is just pressed, just released, or 'currently pressed' 32byte pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS]; 33byte previous_keystate[NUMBUTTONS], current_keystate[NUMBUTTONS]; 34 35unsigned char pump_air_cnt; 36unsigned char pump_liquid_cnt; 37unsigned char last_pixel; 38unsigned char display_row[8]; 39 40const unsigned char test_pattern[] = { 41 0xC0, 0xC0, 0x00, 42 0x40, 0x3C, 0x02, 43 0x40, 0x3C, 0x02, 44 0x40, 0x3C, 0x02, 45 0x40, 0x3C, 0x02, 46 0x40, 0x3C, 0x02, 47 0x40, 0x3C, 0x02, 48}; 49 50 51 52const unsigned char Maker_pattern[] = { 53 0xC0, 0xC0, 0xC0, 54 0x89, 0x92, 0xEE, 55 0xDA, 0x54, 0x89, 56 0xAB, 0xD8, 0xCE, 57 0x8A, 0x54, 0x89, 58 0x8A, 0x52, 0xE9, 59}; 60 61 62const unsigned char Faire_pattern[] = { 63 0xC0, 0xC0, 0xC0, 64 0x73, 0x3B, 0x9C, 65 0x44, 0x92, 0x50, 66 0x77, 0x93, 0x9C, 67 0x44, 0x92, 0x50, 68 0x44, 0xBA, 0x5C, 69}; 70 71 72// program modes 73enum { 74 PM_stop, // program mode stop 75 PM_pump_air, // program mode pump air runs endless 76 PM_pump_liquid, // program mode pump liquid runs endless 77 PM_demo, // program mode full automatic demo 78 PM_demo2, // program mode full automatic demo 79 PM_test, // shows test pattern 80 PM_wait, // wait 1 min in demo 81 PM_wait2, // wait 1 min in demo 82 83}; 84 85// set pin numbers: 86#define buttonStop 0 87#define buttonDemo 1 88#define buttonPumpAir 4 89#define buttonPumpLiquid 3 90#define buttonTest 2 91 92#define pixel_liquid 0 93#define pixel_air 1 94 95#define RIGHT 0 96#define LEFT 1 97#define space_picture_start 10 98//#define space_picture_loop 30 99//#define space_picture_end 62 100#define space_picture_loop 7 101#define space_picture_end 13 102 103#define pump_speed 80 //80 104#define pump_steps 200 105#define pump_delay 100 //100 106 107 108 109AF_Stepper pump_liquid(pump_steps, 2); 110AF_Stepper pump_air(pump_steps, 1); 111 112unsigned char PMode = PM_stop; 113unsigned int wait_cnt; 114/* 115 void draw_pixel_air() { 116 if (pump_air_cnt < 2) { 117 pump_air.step(66, BACKWARD, SINGLE); 118 pump_air_cnt++; 119 } else { 120 pump_air.step(68, BACKWARD,SINGLE); 121 pump_air_cnt = 0; 122 } 123 pump_air.release(); 124 delay(5); 125 } 126 127 void draw_pixel_liquid() { 128 if (pump_liquid_cnt < 2) { 129 pump_liquid.step(66, BACKWARD, SINGLE); 130 pump_liquid_cnt++; 131 } else { 132 pump_liquid.step(68, BACKWARD, SINGLE); 133 pump_liquid_cnt = 0; 134 } 135 pump_liquid.release(); 136 delay(5); 137 } 138*/ 139 140void draw_pixel_air() { 141 pump_air.step(200, FORWARD, DOUBLE); 142 pump_air.release(); 143 //delay(5); 144} 145 146void draw_pixel_liquid() { 147 pump_liquid.step(200, FORWARD, DOUBLE); 148 pump_liquid.release(); 149 //delay(5); 150} 151 152 153 154void copy_line(unsigned char ucline, const unsigned char *pattern) { 155 unsigned char uc1; 156 for (uc1 = 0; uc1 < 3; uc1++) { 157 display_row[uc1] = pattern[(ucline * 3) + uc1]; 158 } 159 160} 161 162void draw_line(unsigned ucdirection) { 163 unsigned char uc1, uc2; 164 if (ucdirection == LEFT) { 165 for (uc1 = 0; uc1 < 3; uc1++) 166 for (uc2 = 0; uc2 < 8; uc2++) { 167 if ((display_row[uc1] << uc2) & 0x80) { 168 if (last_pixel != pixel_liquid) delay(pump_delay); 169 draw_pixel_liquid(); 170 last_pixel = pixel_liquid; 171 } else { 172 if (last_pixel != pixel_air) delay(pump_delay); 173 draw_pixel_air(); 174 last_pixel = pixel_air; 175 } 176 } 177 178 } else { 179 for (uc1 = 3; uc1 > 0; uc1--) 180 for (uc2 = 0; uc2 < 8; uc2++) { 181 if ((display_row[uc1 - 1] >> uc2) & 0x01) { 182 if (last_pixel != pixel_liquid) delay(pump_delay); 183 draw_pixel_liquid(); 184 last_pixel = pixel_liquid; 185 } else { 186 if (last_pixel != pixel_air) delay(pump_delay); 187 draw_pixel_air(); 188 last_pixel = pixel_air; 189 } 190 } 191 } 192 193 194} 195 196void draw_empty_space(unsigned char ucSpace) { 197 unsigned char uc1; 198 for (uc1 = 0; uc1 < ucSpace; uc1++) draw_pixel_air(); 199} 200 201 202void draw_picture(const unsigned char *pattern) { 203 //draw_empty_space(space_picture_start); 204 copy_line(0, pattern); 205 draw_line(RIGHT); 206 draw_empty_space(space_picture_loop); 207 copy_line(1, pattern); 208 draw_line(LEFT); 209 draw_empty_space(space_picture_loop); 210 copy_line(2, pattern); 211 draw_line(RIGHT); 212 draw_empty_space(space_picture_loop); 213 copy_line(3, pattern); 214 draw_line(LEFT); 215 draw_empty_space(space_picture_loop); 216 copy_line(4, pattern); 217 draw_line(RIGHT); 218 draw_empty_space(space_picture_loop); 219 copy_line(5, pattern); 220 draw_line(LEFT); 221 draw_empty_space(space_picture_end); 222} 223 224 225void check_switches() 226{ 227 static byte previousstate[NUMBUTTONS]; 228 static byte currentstate[NUMBUTTONS]; 229 static long lasttime; 230 byte index; 231 if (millis() < lasttime) { 232 lasttime = millis(); // we wrapped around, lets just try again 233 } 234 235 if ((lasttime + DEBOUNCE) > millis()) { 236 return; // not enough time has passed to debounce 237 } 238 // ok we have waited DEBOUNCE milliseconds, lets reset the timer 239 lasttime = millis(); 240 241 for (index = 0; index < NUMBUTTONS; index++) { 242 justpressed[index] = 0; // when we start, we clear out the "just" indicators 243 justreleased[index] = 0; 244 245 currentstate[index] = digitalRead(buttons[index]); // read the button 246 if (currentstate[index] == previousstate[index]) { 247 if ((pressed[index] == HIGH) && (currentstate[index] == HIGH)) { 248 // just pressed 249 justpressed[index] = 1; 250 } 251 else if ((pressed[index] == LOW) && (currentstate[index] == LOW)) { 252 // just released 253 justreleased[index] = 1; 254 } 255 pressed[index] = !currentstate[index]; // remember, digital HIGH means NOT pressed 256 } 257 //Serial.println(pressed[index], DEC); 258 previousstate[index] = currentstate[index]; // keep a running tally of the buttons 259 } 260} 261 262byte thisSwitch_justPressed() { 263 byte thisSwitch = 255; 264 check_switches(); //check the switches & get the current state 265 for (byte i = 0; i < NUMBUTTONS; i++) { 266 current_keystate[i] = justpressed[i]; 267 if (current_keystate[i] != previous_keystate[i]) { 268 if (current_keystate[i]) thisSwitch = i; 269 } 270 previous_keystate[i] = current_keystate[i]; 271 } 272 return thisSwitch; 273} 274 275 276void setup() { 277 byte i; 278 Serial.begin(9600); // set up Serial library at 9600 bps 279 Serial.println("bit.flow!"); 280 // set input pins for keys 281 282 pump_liquid.setSpeed(pump_speed); // 100 rpm 283 pump_air.setSpeed(pump_speed); // 100 rpm 284 pump_liquid.release(); 285 pump_air.release(); 286 287 pump_air_cnt = 0; 288 pump_liquid_cnt = 0; 289 290 // Make input on switch pins 291 for (i = 0; i < NUMBUTTONS; i++) { 292 pinMode(buttons[i], INPUT); 293 } 294 295 296} 297 298void loop() { 299 byte thisSwitch = thisSwitch_justPressed(); 300 switch (thisSwitch) 301 { 302 case buttonStop: 303 Serial.println("switch Stop just pressed"); 304 PMode = PM_stop; 305 break; 306 307 case buttonDemo: 308 Serial.println("switch demo just pressed"); 309 PMode = PM_demo; 310 break; 311 312 case buttonTest: 313 Serial.println("switch test pattern just pressed"); 314 PMode = PM_test; 315 break; 316 317 case buttonPumpLiquid: 318 Serial.println("switch pump liquid just pressed"); 319 PMode = PM_pump_liquid; 320 break; 321 322 case buttonPumpAir: 323 Serial.println("switch pump air just pressed"); 324 PMode = PM_pump_air; 325 break; 326 327 328 } 329 330 331 switch (PMode) { 332 case PM_stop: 333 pump_air.release(); 334 pump_liquid.release(); 335 break; 336 337 case PM_pump_air: 338 draw_pixel_air(); 339 break; 340 341 case PM_pump_liquid: 342 draw_pixel_liquid(); 343 break; 344 345 case PM_test: 346 draw_picture(test_pattern); 347 PMode = PM_stop; 348 break; 349 350 351 case PM_demo: 352 draw_picture(Maker_pattern); 353 wait_cnt = 0; 354 PMode = PM_wait; 355 break; 356 357 case PM_demo2: 358 draw_picture(Faire_pattern); 359 wait_cnt = 0; 360 PMode = PM_wait2; 361 break; 362 363 case PM_wait: 364 delay(10); 365 wait_cnt++; 366 if (wait_cnt > 6000) PMode = PM_demo2; 367 break; 368 369 case PM_wait2: 370 delay(10); 371 wait_cnt++; 372 if (wait_cnt > 6000) PMode = PM_demo; 373 break; 374 375 } 376 377 378 379} 380
Firmware
c_cpp
for Arduino Uno
1 2/* 3 * hose display for Maker Faire Hannover 2016 4 * Version 1.0 5 * Copyright (C) 2016 Hartmut Wendt www.hwhardsoft.de 6 * 7 * 8 * This program is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 20*/ 21 22#include <AFMotor.h> 23#include <font5x7.h> 24 25#define DEBOUNCE 10 // button debouncer, how many ms to debounce, 5+ ms is usually plenty 26 27// here is where we define the buttons that we'll use. button "1" is the first, button "6" is the 6th, etc 28byte buttons[] = {14, 15, 17, 18, 19}; // the analog 0-5 pins are also known as 14-19 29// This handy macro lets us determine how big the array up above is, by checking the size 30#define NUMBUTTONS sizeof(buttons) 31// we will track if a button is just pressed, just released, or 'currently pressed' 32byte pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS]; 33byte previous_keystate[NUMBUTTONS], current_keystate[NUMBUTTONS]; 34 35unsigned char pump_air_cnt; 36unsigned char pump_liquid_cnt; 37unsigned char last_pixel; 38unsigned char display_row[8]; 39 40const unsigned char test_pattern[] = { 41 0xC0, 0xC0, 0x00, 42 0x40, 0x3C, 0x02, 43 0x40, 0x3C, 0x02, 44 0x40, 0x3C, 0x02, 45 0x40, 0x3C, 0x02, 46 0x40, 0x3C, 0x02, 47 0x40, 0x3C, 0x02, 48}; 49 50 51 52const unsigned char Maker_pattern[] = { 53 0xC0, 0xC0, 0xC0, 54 0x89, 0x92, 0xEE, 55 0xDA, 0x54, 0x89, 56 0xAB, 0xD8, 0xCE, 57 0x8A, 0x54, 0x89, 58 0x8A, 0x52, 0xE9, 59}; 60 61 62const unsigned char Faire_pattern[] = { 63 0xC0, 0xC0, 0xC0, 64 0x73, 0x3B, 0x9C, 65 0x44, 0x92, 0x50, 66 0x77, 0x93, 0x9C, 67 0x44, 0x92, 0x50, 68 0x44, 0xBA, 0x5C, 69}; 70 71 72// program modes 73enum { 74 PM_stop, // program mode stop 75 PM_pump_air, // program mode pump air runs endless 76 PM_pump_liquid, // program mode pump liquid runs endless 77 PM_demo, // program mode full automatic demo 78 PM_demo2, // program mode full automatic demo 79 PM_test, // shows test pattern 80 PM_wait, // wait 1 min in demo 81 PM_wait2, // wait 1 min in demo 82 83}; 84 85// set pin numbers: 86#define buttonStop 0 87#define buttonDemo 1 88#define buttonPumpAir 4 89#define buttonPumpLiquid 3 90#define buttonTest 2 91 92#define pixel_liquid 0 93#define pixel_air 1 94 95#define RIGHT 0 96#define LEFT 1 97#define space_picture_start 10 98//#define space_picture_loop 30 99//#define space_picture_end 62 100#define space_picture_loop 7 101#define space_picture_end 13 102 103#define pump_speed 80 //80 104#define pump_steps 200 105#define pump_delay 100 //100 106 107 108 109AF_Stepper pump_liquid(pump_steps, 2); 110AF_Stepper pump_air(pump_steps, 1); 111 112unsigned char PMode = PM_stop; 113unsigned int wait_cnt; 114/* 115 void draw_pixel_air() { 116 if (pump_air_cnt < 2) { 117 pump_air.step(66, BACKWARD, SINGLE); 118 pump_air_cnt++; 119 } else { 120 pump_air.step(68, BACKWARD,SINGLE); 121 pump_air_cnt = 0; 122 } 123 pump_air.release(); 124 delay(5); 125 } 126 127 void draw_pixel_liquid() { 128 if (pump_liquid_cnt < 2) { 129 pump_liquid.step(66, BACKWARD, SINGLE); 130 pump_liquid_cnt++; 131 } else { 132 pump_liquid.step(68, BACKWARD, SINGLE); 133 pump_liquid_cnt = 0; 134 } 135 pump_liquid.release(); 136 delay(5); 137 } 138*/ 139 140void draw_pixel_air() { 141 pump_air.step(200, FORWARD, DOUBLE); 142 pump_air.release(); 143 //delay(5); 144} 145 146void draw_pixel_liquid() { 147 pump_liquid.step(200, FORWARD, DOUBLE); 148 pump_liquid.release(); 149 //delay(5); 150} 151 152 153 154void copy_line(unsigned char ucline, const unsigned char *pattern) { 155 unsigned char uc1; 156 for (uc1 = 0; uc1 < 3; uc1++) { 157 display_row[uc1] = pattern[(ucline * 3) + uc1]; 158 } 159 160} 161 162void draw_line(unsigned ucdirection) { 163 unsigned char uc1, uc2; 164 if (ucdirection == LEFT) { 165 for (uc1 = 0; uc1 < 3; uc1++) 166 for (uc2 = 0; uc2 < 8; uc2++) { 167 if ((display_row[uc1] << uc2) & 0x80) { 168 if (last_pixel != pixel_liquid) delay(pump_delay); 169 draw_pixel_liquid(); 170 last_pixel = pixel_liquid; 171 } else { 172 if (last_pixel != pixel_air) delay(pump_delay); 173 draw_pixel_air(); 174 last_pixel = pixel_air; 175 } 176 } 177 178 } else { 179 for (uc1 = 3; uc1 > 0; uc1--) 180 for (uc2 = 0; uc2 < 8; uc2++) { 181 if ((display_row[uc1 - 1] >> uc2) & 0x01) { 182 if (last_pixel != pixel_liquid) delay(pump_delay); 183 draw_pixel_liquid(); 184 last_pixel = pixel_liquid; 185 } else { 186 if (last_pixel != pixel_air) delay(pump_delay); 187 draw_pixel_air(); 188 last_pixel = pixel_air; 189 } 190 } 191 } 192 193 194} 195 196void draw_empty_space(unsigned char ucSpace) { 197 unsigned char uc1; 198 for (uc1 = 0; uc1 < ucSpace; uc1++) draw_pixel_air(); 199} 200 201 202void draw_picture(const unsigned char *pattern) { 203 //draw_empty_space(space_picture_start); 204 copy_line(0, pattern); 205 draw_line(RIGHT); 206 draw_empty_space(space_picture_loop); 207 copy_line(1, pattern); 208 draw_line(LEFT); 209 draw_empty_space(space_picture_loop); 210 copy_line(2, pattern); 211 draw_line(RIGHT); 212 draw_empty_space(space_picture_loop); 213 copy_line(3, pattern); 214 draw_line(LEFT); 215 draw_empty_space(space_picture_loop); 216 copy_line(4, pattern); 217 draw_line(RIGHT); 218 draw_empty_space(space_picture_loop); 219 copy_line(5, pattern); 220 draw_line(LEFT); 221 draw_empty_space(space_picture_end); 222} 223 224 225void check_switches() 226{ 227 static byte previousstate[NUMBUTTONS]; 228 static byte currentstate[NUMBUTTONS]; 229 static long lasttime; 230 byte index; 231 if (millis() < lasttime) { 232 lasttime = millis(); // we wrapped around, lets just try again 233 } 234 235 if ((lasttime + DEBOUNCE) > millis()) { 236 return; // not enough time has passed to debounce 237 } 238 // ok we have waited DEBOUNCE milliseconds, lets reset the timer 239 lasttime = millis(); 240 241 for (index = 0; index < NUMBUTTONS; index++) { 242 justpressed[index] = 0; // when we start, we clear out the "just" indicators 243 justreleased[index] = 0; 244 245 currentstate[index] = digitalRead(buttons[index]); // read the button 246 if (currentstate[index] == previousstate[index]) { 247 if ((pressed[index] == HIGH) && (currentstate[index] == HIGH)) { 248 // just pressed 249 justpressed[index] = 1; 250 } 251 else if ((pressed[index] == LOW) && (currentstate[index] == LOW)) { 252 // just released 253 justreleased[index] = 1; 254 } 255 pressed[index] = !currentstate[index]; // remember, digital HIGH means NOT pressed 256 } 257 //Serial.println(pressed[index], DEC); 258 previousstate[index] = currentstate[index]; // keep a running tally of the buttons 259 } 260} 261 262byte thisSwitch_justPressed() { 263 byte thisSwitch = 255; 264 check_switches(); //check the switches & get the current state 265 for (byte i = 0; i < NUMBUTTONS; i++) { 266 current_keystate[i] = justpressed[i]; 267 if (current_keystate[i] != previous_keystate[i]) { 268 if (current_keystate[i]) thisSwitch = i; 269 } 270 previous_keystate[i] = current_keystate[i]; 271 } 272 return thisSwitch; 273} 274 275 276void setup() { 277 byte i; 278 Serial.begin(9600); // set up Serial library at 9600 bps 279 Serial.println("bit.flow!"); 280 // set input pins for keys 281 282 pump_liquid.setSpeed(pump_speed); // 100 rpm 283 pump_air.setSpeed(pump_speed); // 100 rpm 284 pump_liquid.release(); 285 pump_air.release(); 286 287 pump_air_cnt = 0; 288 pump_liquid_cnt = 0; 289 290 // Make input on switch pins 291 for (i = 0; i < NUMBUTTONS; i++) { 292 pinMode(buttons[i], INPUT); 293 } 294 295 296} 297 298void loop() { 299 byte thisSwitch = thisSwitch_justPressed(); 300 switch (thisSwitch) 301 { 302 case buttonStop: 303 Serial.println("switch Stop just pressed"); 304 PMode = PM_stop; 305 break; 306 307 case buttonDemo: 308 Serial.println("switch demo just pressed"); 309 PMode = PM_demo; 310 break; 311 312 case buttonTest: 313 Serial.println("switch test pattern just pressed"); 314 PMode = PM_test; 315 break; 316 317 case buttonPumpLiquid: 318 Serial.println("switch pump liquid just pressed"); 319 PMode = PM_pump_liquid; 320 break; 321 322 case buttonPumpAir: 323 Serial.println("switch pump air just pressed"); 324 PMode = PM_pump_air; 325 break; 326 327 328 } 329 330 331 switch (PMode) { 332 case PM_stop: 333 pump_air.release(); 334 pump_liquid.release(); 335 break; 336 337 case PM_pump_air: 338 draw_pixel_air(); 339 break; 340 341 case PM_pump_liquid: 342 draw_pixel_liquid(); 343 break; 344 345 case PM_test: 346 draw_picture(test_pattern); 347 PMode = PM_stop; 348 break; 349 350 351 case PM_demo: 352 draw_picture(Maker_pattern); 353 wait_cnt = 0; 354 PMode = PM_wait; 355 break; 356 357 case PM_demo2: 358 draw_picture(Faire_pattern); 359 wait_cnt = 0; 360 PMode = PM_wait2; 361 break; 362 363 case PM_wait: 364 delay(10); 365 wait_cnt++; 366 if (wait_cnt > 6000) PMode = PM_demo2; 367 break; 368 369 case PM_wait2: 370 delay(10); 371 wait_cnt++; 372 if (wait_cnt > 6000) PMode = PM_demo; 373 break; 374 375 } 376 377 378 379} 380
Downloadable files
Schematic Overview
Block diagram
Schematic Overview
Comments
Only logged in users can leave comments
hwhardsoft
0 Followers
•0 Projects
Table of contents
Intro
39
0