Difference between revisions of "Andon light"

From Hackerspace ACKspace
Jump to: navigation, search
(set project to completed)
m (project stalled needs second midi port fixed)
 
(14 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
{{Project
 
{{Project
|State=Completed
+
|Featured=No
 +
|State=Stalled
 
|Members=xopr
 
|Members=xopr
 
|Description=Andon light/signal tower
 
|Description=Andon light/signal tower
 +
|GitHub=midi-andon
 +
|Picture=andon_in_the_space.jpg
 
}}
 
}}
 
== synopsis ==
 
== synopsis ==
 +
[[File:Off the Hook at CCC 2011.jpg|thumb|right|400px|Andon live in the studio]]
 
An andon light is a color-coded visual display for process state control; in short: On-Air light
 
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.
+
The first version is completed, and used in the Binary Voice studio at the [[CCC2011]].
 
+
The second version was for [[OHM2013]]..
It is now located in the space as mood-light
+
The third version was for [[SHA2017]] but the second midi port (for the second mixer) failed and needs to be looked at for the next revision (H-2021)..
 
 
[[Image:andon_live.jpg|left|400px|Andon live in the studio]]
 
[[Media:andon_in_the_space.jpg|left|400px|Andon in the space]]
 
 
 
 
 
  
 
== implementation ==
 
== implementation ==
Line 21: Line 20:
 
=== prototype ===
 
=== prototype ===
 
Since the media plugin doesn't work, you have to open the file manually:
 
Since the media plugin doesn't work, you have to open the file manually:
[[Media:andon_prototype.mov]]
+
{{#Widget:Html5media|url={{filepath:Andon_prototype.mov}}}}
  
=== first version ===
+
=== andon 1.0 ===
 +
<div class="mw-collapsible mw-collapsed" id="mw-customcollapsible-andon_ino">
 
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.
 
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) ===
+
<div class="mw-customtoggle-andon_ino mw-code">Click here to view the source code</div>
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.
+
<pre class="mw-collapsible-content">
 +
  //#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);
 +
    }
 +
  }
 +
</pre>
 +
</div>
 +
 
 +
=== andon 2.0 ===
 +
 
 +
Currently being worked on..
 +
 
 +
It does:
 +
* do on-board MIDI
 +
* work stand-alone
 +
* switch a 220V 2A relay output as well
  
 
=== todo ===
 
=== todo ===
 
* publish both PC c++ midi-to-serial-instructions code as well as the arduino source
 
* publish both PC c++ midi-to-serial-instructions code as well as the arduino source
 +
* read values from EEPROM
 +
* store values to EEPROM
 +
* add relay that can switch outlet power
 +
 +
Location: at [[Location::user:xopr|xopr's]]
 +
[[Category:Arduino]][[Category:LEDs]]

Latest revision as of 10:46, 10 April 2018

Project: Andon light
Featured: No
State Stalled
Members xopr
GitHub midi-andon
Description Andon light/signal tower
Picture
Andon in the space.jpg

synopsis

Andon live in the studio

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. The second version was for OHM2013.. The third version was for SHA2017 but the second midi port (for the second mixer) failed and needs to be looked at for the next revision (H-2021)..

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:

andon 1.0

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.

Click here to view the source code
   //#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);
     }
   }

andon 2.0

Currently being worked on..

It does:

  • do on-board MIDI
  • work stand-alone
  • switch a 220V 2A relay output as well

todo

  • publish both PC c++ midi-to-serial-instructions code as well as the arduino source
  • read values from EEPROM
  • store values to EEPROM
  • add relay that can switch outlet power

Location: at xopr's