Difference between revisions of "Andon light"
m |
(added Arduino source code) |
||
Line 13: | Line 13: | ||
It is now located in the space as mood-light | It is now located in the space as mood-light | ||
+ | <div> | ||
+ | //#define _DEBUG | ||
+ | |||
+ | enum SwitchMode | ||
+ | { | ||
+ | Slow, | ||
+ | Normal, | ||
+ | Fast | ||
+ | }; | ||
+ | |||
+ | enum LoopMode | ||
+ | { | ||
+ | SingleShot, | ||
+ | Bounce, | ||
+ | Loop | ||
+ | }; | ||
+ | |||
+ | enum Pins | ||
+ | { | ||
+ | Red = 0, | ||
+ | Orange, | ||
+ | Green, | ||
+ | Blue | ||
+ | }; | ||
+ | |||
+ | const int pTelephone = 15; | ||
+ | |||
+ | void DebugPrint( char* _strInfo ) | ||
+ | { | ||
+ | #ifdef _DEBUG | ||
+ | Serial.println( _strInfo ); | ||
+ | #endif | ||
+ | } | ||
+ | |||
+ | void DebugPrint( int _nInfo ) | ||
+ | { | ||
+ | #ifdef _DEBUG | ||
+ | Serial.print( _nInfo ); | ||
+ | Serial.print( ", " ); | ||
+ | #endif | ||
+ | } | ||
+ | |||
+ | |||
+ | // The analogue have 17 values due to inverse square law on led brighness | ||
+ | static const byte MAX_INDEX = 16; | ||
+ | static const byte s_fadeValues[] = { 255, 180, 128, 90, 64, 45, 32, 23, 16, 12, 8, 6, 4, 3, 2, 1, 0 }; | ||
+ | static const byte s_slowBlinkValues[] = { 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
+ | static const byte s_fastBlinkValues[] = { 255, 255, 255, 255, 255, 0, 0, 0, 255, 255, 255, 255, 255, 0, 0, 0, 0 }; | ||
+ | |||
+ | // the colors are red, orange, green and blue respectively | ||
+ | // serial light instructions | ||
+ | static const byte s_onCommand[] = { '!', '@', '#', '$' }; | ||
+ | static const byte s_offCommand[] = { '1', '2', '3', '4' }; | ||
+ | |||
+ | // output pins | ||
+ | static const byte s_pins[] = { 3, 5, 6, 9 }; | ||
+ | |||
+ | // values (off) | ||
+ | volatile byte g_values[] = { MAX_INDEX, MAX_INDEX, MAX_INDEX, MAX_INDEX }; | ||
+ | |||
+ | // step | ||
+ | volatile byte g_step[] = { 0, 0, 0, 0 }; | ||
+ | |||
+ | // light operation modes | ||
+ | volatile SwitchMode g_eSwitchMode[] = { Normal, Normal, Normal, Normal }; | ||
+ | volatile SwitchMode g_eCurrentSwitchMode = Normal; | ||
+ | |||
+ | volatile LoopMode g_eLoopMode[] = { SingleShot, SingleShot, SingleShot, SingleShot }; | ||
+ | volatile LoopMode g_eCurrentLoopMode = SingleShot; | ||
+ | |||
+ | void setup( ) | ||
+ | { | ||
+ | Serial.begin( 9600 ); | ||
+ | |||
+ | // make it output | ||
+ | pinMode( s_pins[ Red ], OUTPUT ); | ||
+ | pinMode( s_pins[ Orange ], OUTPUT ); | ||
+ | pinMode( s_pins[ Green ], OUTPUT ); | ||
+ | pinMode( s_pins[ Blue ], OUTPUT ); | ||
+ | |||
+ | /* | ||
+ | pinMode( pTelephone, INPUT ); | ||
+ | digitalWrite( pTelephone, LOW ); | ||
+ | |||
+ | pinMode( 14, INPUT ); | ||
+ | digitalWrite( 14, LOW ); | ||
+ | |||
+ | pinMode( 20, INPUT ); | ||
+ | digitalWrite( 20, LOW ); | ||
+ | */ | ||
+ | |||
+ | // wait to make sure serial is initialized on the host | ||
+ | delay(1000); | ||
+ | |||
+ | DebugPrint( "initialization done, starting demo mode" ); | ||
+ | |||
+ | demoMode( ); | ||
+ | } | ||
+ | |||
+ | void loop( ) | ||
+ | { | ||
+ | byte idx; | ||
+ | byte nCurrentPinValue; | ||
+ | |||
+ | // check if data has been sent from the computer: | ||
+ | if (Serial.available( )) | ||
+ | { | ||
+ | byte input; | ||
+ | // read the most recent byte (which will be from 0 to 255): | ||
+ | input = Serial.read( ); | ||
+ | |||
+ | switch ( input ) | ||
+ | { | ||
+ | // switch mode | ||
+ | case 's': | ||
+ | case 'S': | ||
+ | DebugPrint( "switching to slow mode" ); | ||
+ | g_eCurrentSwitchMode = Slow; | ||
+ | break; | ||
+ | case 'n': | ||
+ | case 'N': | ||
+ | DebugPrint( "switching to normal mode" ); | ||
+ | g_eCurrentSwitchMode = Normal; | ||
+ | break; | ||
+ | case 'f': | ||
+ | case 'F': | ||
+ | DebugPrint( "switching to fast mode" ); | ||
+ | g_eCurrentSwitchMode = Fast; | ||
+ | break; | ||
+ | // loop mode | ||
+ | case 'o': | ||
+ | case 'O': | ||
+ | DebugPrint( "switching to single shot mode" ); | ||
+ | g_eCurrentLoopMode = SingleShot; // aka once | ||
+ | break; | ||
+ | case 'b': | ||
+ | case 'B': | ||
+ | DebugPrint( "switching to bounce mode" ); | ||
+ | g_eCurrentLoopMode = Bounce; | ||
+ | break; | ||
+ | case 'l': | ||
+ | case 'L': | ||
+ | DebugPrint( "switching to loop mode" ); | ||
+ | g_eCurrentLoopMode = Loop; | ||
+ | break; | ||
+ | |||
+ | // version | ||
+ | case 'v': | ||
+ | case 'V': | ||
+ | case 'h': | ||
+ | case 'H': | ||
+ | Serial.println("xopr's Andon Light v0.2"); | ||
+ | Serial.println(""); | ||
+ | Serial.println(" Usage:"); | ||
+ | Serial.println(" [snf]?[obl]?([1234]|[!@#$])"); | ||
+ | Serial.println(""); | ||
+ | Serial.println(" Switch modes:"); | ||
+ | Serial.println(" [s]low"); | ||
+ | Serial.println(" [n]ormal"); | ||
+ | Serial.println(" [f]ast"); | ||
+ | Serial.println(""); | ||
+ | Serial.println(" Loop modes:"); | ||
+ | Serial.println(" [o]ne shot"); | ||
+ | Serial.println(" [b]bounce"); | ||
+ | Serial.println(" [l]loop"); | ||
+ | Serial.println(""); | ||
+ | Serial.println(" Lights:"); | ||
+ | Serial.println(" {1!}: Red"); | ||
+ | Serial.println(" {2@}: Orange"); | ||
+ | Serial.println(" {3#}: Green"); | ||
+ | Serial.println(" {4$}: Blue"); | ||
+ | |||
+ | break; | ||
+ | |||
+ | // assume it's a switch command | ||
+ | default: | ||
+ | for ( idx = 0; idx < 4; idx++ ) | ||
+ | { | ||
+ | if ( input == s_onCommand[ idx ] ) | ||
+ | { | ||
+ | // apply the optionally prefixed or default modes | ||
+ | applyModes( idx ); | ||
+ | |||
+ | // set the stepping, so we know that we need to update the output port | ||
+ | g_step[ idx ] = -1; | ||
+ | |||
+ | // special mode: normal single shot means just toggle the state | ||
+ | if ( g_eSwitchMode[ idx ] == Normal && g_eLoopMode[ idx ] == SingleShot ) | ||
+ | { | ||
+ | DebugPrint( "ultra fast on!!1`" ); | ||
+ | g_values[ idx ] = -g_step[ idx ]; | ||
+ | } | ||
+ | |||
+ | // since we found our character, break out of the loop | ||
+ | break; | ||
+ | } | ||
+ | if ( input == s_offCommand[ idx ] ) | ||
+ | { | ||
+ | // set the stepping, so we know that we need to update the output port | ||
+ | g_step[ idx ] = 1; | ||
+ | |||
+ | // special mode: normal single shot means just toggle the state | ||
+ | if ( g_eSwitchMode[ idx ] == Normal && g_eLoopMode[ idx ] == SingleShot ) | ||
+ | { | ||
+ | DebugPrint( "ultra fast off!!1`" ); | ||
+ | g_values[ idx ] = MAX_INDEX - g_step[ idx ]; | ||
+ | } | ||
+ | |||
+ | // apply the optionally prefixed or default modes | ||
+ | applyModes( idx ); | ||
+ | |||
+ | // since we found our character, break out of the loop | ||
+ | break; | ||
+ | } | ||
+ | } // for | ||
+ | break; | ||
+ | } // switch input | ||
+ | } // serial.available | ||
+ | |||
+ | // now do the stepping check/iteration on the lights | ||
+ | for ( idx = 0; idx < 4; idx++ ) | ||
+ | { | ||
+ | if ( g_step[ idx ] ) | ||
+ | { | ||
+ | |||
+ | /* | ||
+ | b0rken | ||
+ | // update the current value, if needed | ||
+ | if ((g_step[ idx ] < 0 && g_values[ idx ] <= 0) | ||
+ | || (g_step[ idx ] > 0 && g_values[ idx ] >= MAX_INDEX )) | ||
+ | { | ||
+ | g_step[ idx ] = 0; | ||
+ | continue; | ||
+ | } | ||
+ | */ | ||
+ | |||
+ | g_values[ idx ] += g_step[ idx ]; | ||
+ | |||
+ | // reached the boundaries? update the stepping (and prolly the loopmode) | ||
+ | if ( g_values[ idx ] <= 0 || g_values[ idx ] >= MAX_INDEX ) | ||
+ | { | ||
+ | // reset stepper if we're done with single shot or return | ||
+ | if ( g_eLoopMode[ idx ] == SingleShot ) | ||
+ | { | ||
+ | DebugPrint( idx ); | ||
+ | DebugPrint( " is done" ); | ||
+ | g_step[ idx ] = 0; | ||
+ | } | ||
+ | else | ||
+ | // invert stepping | ||
+ | g_step[ idx ] = -g_step[ idx ]; | ||
+ | |||
+ | // after a bounce, loopmode changes into single shot | ||
+ | if ( g_eLoopMode[ idx ] == Bounce ) | ||
+ | { | ||
+ | DebugPrint( idx ); | ||
+ | DebugPrint( " bounced to single shot mode" ); | ||
+ | g_eLoopMode[ idx ] = SingleShot; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | switch ( g_eSwitchMode[ idx ] ) | ||
+ | { | ||
+ | case Slow: | ||
+ | nCurrentPinValue = s_fadeValues[ min( g_values[ idx ], MAX_INDEX ) ]; | ||
+ | break; | ||
+ | case Normal: | ||
+ | nCurrentPinValue = s_slowBlinkValues[ min( g_values[ idx ], MAX_INDEX ) ]; | ||
+ | break; | ||
+ | case Fast: | ||
+ | nCurrentPinValue = s_fastBlinkValues[ min( g_values[ idx ], MAX_INDEX ) ]; | ||
+ | break; | ||
+ | } | ||
+ | |||
+ | analogWrite( s_pins[ idx ], nCurrentPinValue ); | ||
+ | } // if stepping | ||
+ | } // for | ||
+ | |||
+ | /* | ||
+ | if ( digitalRead( pTelephone ) == LOW ) | ||
+ | digitalWrite( s_pins[ Blue ], HIGH ); | ||
+ | |||
+ | if ( analogRead( pTelephone ) >= 1022 ) | ||
+ | digitalWrite( s_pins[ Blue ], HIGH ); | ||
+ | */ | ||
+ | |||
+ | /* | ||
+ | Serial.println( analogRead( pTelephone ) ); | ||
+ | Serial.println( analogRead( pTelephone ) ); | ||
+ | Serial.print( " " ); | ||
+ | Serial.print( analogRead( 14 ) ); | ||
+ | Serial.print( " " ); | ||
+ | Serial.print( analogRead( 15 ) ); | ||
+ | Serial.print( " " ); | ||
+ | Serial.print( analogRead( 16 ) ); | ||
+ | Serial.print( " " ); | ||
+ | Serial.println( analogRead( 17 ) ); | ||
+ | */ | ||
+ | |||
+ | delay( 50 ); | ||
+ | } | ||
+ | |||
+ | void applyModes( byte _idx ) | ||
+ | { | ||
+ | |||
+ | // apply the current modes | ||
+ | if ( g_eSwitchMode[ _idx ] != g_eCurrentSwitchMode || g_eLoopMode[ _idx ] != g_eCurrentLoopMode ) | ||
+ | { | ||
+ | g_eSwitchMode[ _idx ] = g_eCurrentSwitchMode; | ||
+ | g_eLoopMode[ _idx ] = g_eCurrentLoopMode; | ||
+ | DebugPrint( _idx ); | ||
+ | DebugPrint( " has new mode applied" ); | ||
+ | } | ||
+ | |||
+ | // reset the current modes | ||
+ | g_eCurrentSwitchMode = Normal; | ||
+ | g_eCurrentLoopMode = SingleShot; | ||
+ | } | ||
+ | |||
+ | void demoMode( ) | ||
+ | { | ||
+ | byte idx; | ||
+ | |||
+ | // set values and stepping | ||
+ | g_values[ Red ] = 17; | ||
+ | g_values[ Orange ] = 13; | ||
+ | g_values[ Green ] = 10; | ||
+ | g_values[ Blue ] = 6; | ||
+ | |||
+ | for ( idx = 0; idx < 4; idx++ ) | ||
+ | g_step[ idx ] = -1; | ||
+ | |||
+ | while ( !Serial.available( )) | ||
+ | { | ||
+ | for ( idx = 0; idx < 4; idx++ ) | ||
+ | { | ||
+ | g_values[ idx ] += g_step[ idx ]; | ||
+ | |||
+ | if ( g_values[ idx ] >= 30 ) | ||
+ | { | ||
+ | //DebugPrint( idx ); | ||
+ | //DebugPrint( ": value >= 30 == off" ); | ||
+ | g_step[ idx ] = -1; | ||
+ | } | ||
+ | else if ( g_values[ idx ] <= 0 ) | ||
+ | { | ||
+ | //DebugPrint( idx ); | ||
+ | //DebugPrint( ": value <= 30 == on" ); | ||
+ | g_step[ idx ] = 1; | ||
+ | } | ||
+ | |||
+ | analogWrite( s_pins[ idx ], s_fadeValues[ min( g_values[ idx ], MAX_INDEX ) ] ); | ||
+ | } | ||
+ | |||
+ | delay( 50 ); | ||
+ | } | ||
+ | |||
+ | DebugPrint( "end of demo mode. cleaning up" ); | ||
+ | |||
+ | for ( idx = 0; idx < 4; idx++ ) | ||
+ | { | ||
+ | g_step[ idx] = 0; | ||
+ | g_values[ idx ] = MAX_INDEX; | ||
+ | digitalWrite( s_pins[ idx ], LOW); | ||
+ | } | ||
+ | } | ||
+ | </div> | ||
== implementation == | == implementation == |
Revision as of 20:40, 2 September 2011
Project: Andon light | |
---|---|
Featured: | |
State | Completed |
Members | xopr |
GitHub | No GitHub project defined. Add your project here. |
Description | Andon light/signal tower |
Picture | |
No project picture! Fill in form Picture or Upload a jpeg here |
synopsis
An andon light is a color-coded visual display for process state control; in short: On-Air light
The first version is completed, and used in the Binary Voice studio at the CCC2011.
It is now located in the space as mood-light
//#define _DEBUG enum SwitchMode { Slow, Normal, Fast }; enum LoopMode { SingleShot, Bounce, Loop }; enum Pins { Red = 0, Orange, Green, Blue }; const int pTelephone = 15; void DebugPrint( char* _strInfo ) { #ifdef _DEBUG Serial.println( _strInfo ); #endif } void DebugPrint( int _nInfo ) { #ifdef _DEBUG Serial.print( _nInfo ); Serial.print( ", " ); #endif } // The analogue have 17 values due to inverse square law on led brighness static const byte MAX_INDEX = 16; static const byte s_fadeValues[] = { 255, 180, 128, 90, 64, 45, 32, 23, 16, 12, 8, 6, 4, 3, 2, 1, 0 }; static const byte s_slowBlinkValues[] = { 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static const byte s_fastBlinkValues[] = { 255, 255, 255, 255, 255, 0, 0, 0, 255, 255, 255, 255, 255, 0, 0, 0, 0 }; // the colors are red, orange, green and blue respectively // serial light instructions static const byte s_onCommand[] = { '!', '@', '#', '$' }; static const byte s_offCommand[] = { '1', '2', '3', '4' }; // output pins static const byte s_pins[] = { 3, 5, 6, 9 }; // values (off) volatile byte g_values[] = { MAX_INDEX, MAX_INDEX, MAX_INDEX, MAX_INDEX }; // step volatile byte g_step[] = { 0, 0, 0, 0 }; // light operation modes volatile SwitchMode g_eSwitchMode[] = { Normal, Normal, Normal, Normal }; volatile SwitchMode g_eCurrentSwitchMode = Normal; volatile LoopMode g_eLoopMode[] = { SingleShot, SingleShot, SingleShot, SingleShot }; volatile LoopMode g_eCurrentLoopMode = SingleShot; void setup( ) { Serial.begin( 9600 ); // make it output pinMode( s_pins[ Red ], OUTPUT ); pinMode( s_pins[ Orange ], OUTPUT ); pinMode( s_pins[ Green ], OUTPUT ); pinMode( s_pins[ Blue ], OUTPUT ); /* pinMode( pTelephone, INPUT ); digitalWrite( pTelephone, LOW ); pinMode( 14, INPUT ); digitalWrite( 14, LOW ); pinMode( 20, INPUT ); digitalWrite( 20, LOW ); */ // wait to make sure serial is initialized on the host delay(1000); DebugPrint( "initialization done, starting demo mode" ); demoMode( ); } void loop( ) { byte idx; byte nCurrentPinValue; // check if data has been sent from the computer: if (Serial.available( )) { byte input; // read the most recent byte (which will be from 0 to 255): input = Serial.read( ); switch ( input ) { // switch mode case 's': case 'S': DebugPrint( "switching to slow mode" ); g_eCurrentSwitchMode = Slow; break; case 'n': case 'N': DebugPrint( "switching to normal mode" ); g_eCurrentSwitchMode = Normal; break; case 'f': case 'F': DebugPrint( "switching to fast mode" ); g_eCurrentSwitchMode = Fast; break; // loop mode case 'o': case 'O': DebugPrint( "switching to single shot mode" ); g_eCurrentLoopMode = SingleShot; // aka once break; case 'b': case 'B': DebugPrint( "switching to bounce mode" ); g_eCurrentLoopMode = Bounce; break; case 'l': case 'L': DebugPrint( "switching to loop mode" ); g_eCurrentLoopMode = Loop; break; // version case 'v': case 'V': case 'h': case 'H': Serial.println("xopr's Andon Light v0.2"); Serial.println(""); Serial.println(" Usage:"); Serial.println(" [snf]?[obl]?([1234]|[!@#$])"); Serial.println(""); Serial.println(" Switch modes:"); Serial.println(" [s]low"); Serial.println(" [n]ormal"); Serial.println(" [f]ast"); Serial.println(""); Serial.println(" Loop modes:"); Serial.println(" [o]ne shot"); Serial.println(" [b]bounce"); Serial.println(" [l]loop"); Serial.println(""); Serial.println(" Lights:"); Serial.println(" {1!}: Red"); Serial.println(" {2@}: Orange"); Serial.println(" {3#}: Green"); Serial.println(" {4$}: Blue"); break; // assume it's a switch command default: for ( idx = 0; idx < 4; idx++ ) { if ( input == s_onCommand[ idx ] ) { // apply the optionally prefixed or default modes applyModes( idx ); // set the stepping, so we know that we need to update the output port g_step[ idx ] = -1; // special mode: normal single shot means just toggle the state if ( g_eSwitchMode[ idx ] == Normal && g_eLoopMode[ idx ] == SingleShot ) { DebugPrint( "ultra fast on!!1`" ); g_values[ idx ] = -g_step[ idx ]; } // since we found our character, break out of the loop break; } if ( input == s_offCommand[ idx ] ) { // set the stepping, so we know that we need to update the output port g_step[ idx ] = 1; // special mode: normal single shot means just toggle the state if ( g_eSwitchMode[ idx ] == Normal && g_eLoopMode[ idx ] == SingleShot ) { DebugPrint( "ultra fast off!!1`" ); g_values[ idx ] = MAX_INDEX - g_step[ idx ]; } // apply the optionally prefixed or default modes applyModes( idx ); // since we found our character, break out of the loop break; } } // for break; } // switch input } // serial.available // now do the stepping check/iteration on the lights for ( idx = 0; idx < 4; idx++ ) { if ( g_step[ idx ] ) { /* b0rken // update the current value, if needed if ((g_step[ idx ] < 0 && g_values[ idx ] <= 0) || (g_step[ idx ] > 0 && g_values[ idx ] >= MAX_INDEX )) { g_step[ idx ] = 0; continue; } */ g_values[ idx ] += g_step[ idx ]; // reached the boundaries? update the stepping (and prolly the loopmode) if ( g_values[ idx ] <= 0 || g_values[ idx ] >= MAX_INDEX ) { // reset stepper if we're done with single shot or return if ( g_eLoopMode[ idx ] == SingleShot ) { DebugPrint( idx ); DebugPrint( " is done" ); g_step[ idx ] = 0; } else // invert stepping g_step[ idx ] = -g_step[ idx ]; // after a bounce, loopmode changes into single shot if ( g_eLoopMode[ idx ] == Bounce ) { DebugPrint( idx ); DebugPrint( " bounced to single shot mode" ); g_eLoopMode[ idx ] = SingleShot; } } switch ( g_eSwitchMode[ idx ] ) { case Slow: nCurrentPinValue = s_fadeValues[ min( g_values[ idx ], MAX_INDEX ) ]; break; case Normal: nCurrentPinValue = s_slowBlinkValues[ min( g_values[ idx ], MAX_INDEX ) ]; break; case Fast: nCurrentPinValue = s_fastBlinkValues[ min( g_values[ idx ], MAX_INDEX ) ]; break; } analogWrite( s_pins[ idx ], nCurrentPinValue ); } // if stepping } // for /* if ( digitalRead( pTelephone ) == LOW ) digitalWrite( s_pins[ Blue ], HIGH ); if ( analogRead( pTelephone ) >= 1022 ) digitalWrite( s_pins[ Blue ], HIGH ); */ /* Serial.println( analogRead( pTelephone ) ); Serial.println( analogRead( pTelephone ) ); Serial.print( " " ); Serial.print( analogRead( 14 ) ); Serial.print( " " ); Serial.print( analogRead( 15 ) ); Serial.print( " " ); Serial.print( analogRead( 16 ) ); Serial.print( " " ); Serial.println( analogRead( 17 ) ); */ delay( 50 ); } void applyModes( byte _idx ) { // apply the current modes if ( g_eSwitchMode[ _idx ] != g_eCurrentSwitchMode || g_eLoopMode[ _idx ] != g_eCurrentLoopMode ) { g_eSwitchMode[ _idx ] = g_eCurrentSwitchMode; g_eLoopMode[ _idx ] = g_eCurrentLoopMode; DebugPrint( _idx ); DebugPrint( " has new mode applied" ); } // reset the current modes g_eCurrentSwitchMode = Normal; g_eCurrentLoopMode = SingleShot; } void demoMode( ) { byte idx; // set values and stepping g_values[ Red ] = 17; g_values[ Orange ] = 13; g_values[ Green ] = 10; g_values[ Blue ] = 6; for ( idx = 0; idx < 4; idx++ ) g_step[ idx ] = -1; while ( !Serial.available( )) { for ( idx = 0; idx < 4; idx++ ) { g_values[ idx ] += g_step[ idx ]; if ( g_values[ idx ] >= 30 ) { //DebugPrint( idx ); //DebugPrint( ": value >= 30 == off" ); g_step[ idx ] = -1; } else if ( g_values[ idx ] <= 0 ) { //DebugPrint( idx ); //DebugPrint( ": value <= 30 == on" ); g_step[ idx ] = 1; } analogWrite( s_pins[ idx ], s_fadeValues[ min( g_values[ idx ], MAX_INDEX ) ] ); } delay( 50 ); } DebugPrint( "end of demo mode. cleaning up" ); for ( idx = 0; idx < 4; idx++ ) { g_step[ idx] = 0; g_values[ idx ] = MAX_INDEX; digitalWrite( s_pins[ idx ], LOW); } }
implementation
I used a light tower/andon light which a good friend Spert modified to fit 6 leds in it.
prototype
Since the media plugin doesn't work, you have to open the file manually: Media:andon_prototype.mov
first version
The first version listens on a serial port and change the lights depending on the data it receives. On the PC, an application listens to the midi signals and above certain channel thresholds, it will send out the correct signal data over the serial port.
future version(s)
Create an andon light which has a MIDI port on-board where all the logic is inside the Arduino/AVR with channel thresholds on the internal ROM.
todo
- publish both PC c++ midi-to-serial-instructions code as well as the arduino source