How to check if value has changed in void loop?

Hi there,

Was just wondering if somebody could possibly help me with some code?

I had this all working fine (I'm fairly certain I did anyway) but left the project for about a year or so and in that time for some reason it now doesn't do everything it used to do. I don't know why that is as I've literally not touched the board since that time so the code on the board is exactly as I left it.

I have code which is more or less working fully which is basically code that when you press a key on a digital piano (MIDI based) then an LED strip (WS812B) lights up the corresponding LEDs above the key pressed. The lights all light up fine but I'm having a couple of problems which I need help with.

The first being an Arduino IDE issue in that I have some serial print lines in the code to help me follow what is going on except they are firing all the while (they're inside the void loop part of the code) and so the serial monitor is scrolling all the while and is impossible to read. I've tried clicking on the Toggle Autoscroll button (OSX) but it never stops scrolling so I've got no real chance of reading the values very easily :frowning:

The second issue being that in my project I have 3 potentiometers attached to the board to be able to set the hue, saturation and brightness (value) of the LEDs. The hue potentiometer works fine and changes the colour of the LEDs but now for some reason the other two aren't changing the LEDs in any way at all.

I've checked that the pots are still working correctly with an ohmeter and they are all working fine so not too sure what is going on.

Therefore to cover these issues I'd like to be able to in my code only print out the values in the loop from each of the pots being read but only if the value is different to the previous read value.

This will enable me to not have the serial monitor spitting out tons and tons of data and also I'll be able to see right away if the values are changing or not.

Also if anyone can see any glaring reason for the saturation and value (brightness) code not working (it's definitely possible that I didn't have this all working after all but it's been such a long time that I'm not totally sure now :frowning: - I'm fairly positive I remember seeing all the pots working though) then I'd really appreciate any help with that. Thank you.

The code so far is as follows :

/*
   MIDIUSB_test.ino

   Created: 4/6/2015 10:47:08 AM
   Author: gurbrinder grewal
   Modified by Arduino LLC (2015)
*/

// a lookup table to convert pitch to text
const char pitchLUT[][4] =
{
  " A0", "B0b", " B0", " C1", "D1b", " D1", "E1b", " E1", " F1", "G1b",
  " G1", "A1b", " A1", "B1b", " B1", " C2", "D2b", " D2", "E2b", " E2",
  " F2", "G2b", " G2", "A2b", " A2", "B2b", " B2", " C3", "D3b", " D3",
  "E3b", " E3", " F3", "G3b", " G3", "A3b", " A3", "B3b", " B3", " C4",
  "D4b", " D4", " E4b", " E4", " F4", "G4b", " G4", "A4b", "A4", "B4b",
  " B4", " C5", "D5b", " D5", "E5b", " E5", " F5", "G5b", " G5", "A5b",
  " A5", "B5b", " B5", " C6", "D6b", " D6", "E6b", " E6", " F6", "G6b",
  " G6", "A6b", " A6", "B6b", " B6", " C7", "D7b", " D7", "E7b", " E7",
  " F7", "G7b", " G7", "A7b", " A7", "B7b", " B7", " C8",
};

#include "MIDIUSB.h"
#include "FastLED.h"
#define DEBUG                   1             // Comment out to stop verbose serial messages
#define DATA_PIN                3             // Output Pin to Data Line on Strip
#define COLOR_ORDER             GRB           // I had to change this for my strip if your color is off then you know.
#define NUM_LEDS                176           // # of LEDS in the strip
#define BRIGHTNESS              220            // Maximum brightness of LEDs
#define LED_TYPE                WS2812B       // WS2812B or WS2811 or whatever
#define MAX_POWER_MILLIAMPS     4000          // Max power draw that LED strip can pull
#define HUE_POT_PIN             A0            // Pin that Pot is attached to for setting LED hue
#define SATURATION_POT_PIN      A1            // Pin that Pot is attached to for setting LED saturation
#define VALUE_POT_PIN           A2            // Pin that Pot is attached to for setting LED value (brightness)

CRGB leds[NUM_LEDS];




uint8_t
evtCIN,
evtType,
evtChan,
evtPitch,
evtVel,
pitch;
char
szStr[40];



void setup()
{
  // Sanity check delay - allows reprogramming if accidently blowing power w/leds
  delay(2000);
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
  FastLED.setMaxPowerInVoltsAndMilliamps( 5, MAX_POWER_MILLIAMPS);
  FastLED.setBrightness(BRIGHTNESS);
  FastLED.clear();
  Serial.begin(115200);
}





void loop()

{

  // Read our HUE potentiometer (A0) input and set a variable hue_pot to be used below
  uint16_t huePotRead = analogRead(HUE_POT_PIN);
  uint8_t hue_pot = map(huePotRead, 0, 1023, 0, 255);
  Serial.print( "Hue = ");
  Serial.println( hue_pot );
  // Read our SATURATION potentiometer (A1) input and set a variable saturation_pot to be used below
  uint16_t saturationPotRead = analogRead(SATURATION_POT_PIN);
  uint8_t saturation_pot = map(saturationPotRead, 0, 1023, 0, 255);
  Serial.print( "Saturation = ");  
  Serial.println( saturation_pot );
  // Read our VALUE potentiometer (A2) input and set a variable value_pot to be used below
  uint16_t valuePotRead = analogRead(VALUE_POT_PIN);
  uint8_t value_pot = map(valuePotRead, 0, 1023, 0, 255);
  Serial.print( "Value = ");  
  Serial.println( value_pot );
   // Fade all LEDs down by 1 in brightness each time this is called
//   fadeToBlackBy(leds, NUM_LEDS-1, 10);
//   FastLED.show();

  midiEventPacket_t rx = MidiUSB.read();
  if ( rx.header != 0 )
  {
    do
    {
#ifdef DEBUG
      sprintf( szStr, "Packet: %02X - %02X - %02X - %02X",
               rx.header,
               rx.byte1,
               rx.byte2,
               rx.byte3 );
      // Serial.println( szStr );
#endif
      evtCIN = rx.header & 0xf;
      evtType = (rx.byte1 >> 4) & 0xf;
      evtChan = rx.byte1 & 0xf;
      evtPitch = rx.byte2;
      evtVel = rx.byte3;
      switch ( evtCIN )
      {
        case    0x8:
        case    0x9:
          if ( evtPitch >= 21 && evtPitch <= 108 )
          {
            evtPitch -= 21;
            if ( evtType == 0x8 || (evtType == 0x9 && evtVel == 0) )
            {
              leds[evtPitch << 1] = CRGB::Black;
              leds[(evtPitch << 1) + 1] = CRGB::Black;
              // Fade all LEDs down by 1 in brightness each time this is called
//              leds[evtPitch << 1].fadeToBlackBy(0);
//              leds[(evtPitch << 1) + 1].fadeToBlackBy(0);
            }
            else
            {
              // LED Brightness set depending upon velocity key is played at!
              //leds[evtPitch << 1] = CHSV(150, 255, evtVel*2);
              //leds[(evtPitch << 1) + 1] = CHSV(150, 255, evtVel*2);
              // Standard way of setting LEDs using CHSV
//              int LED_HUE = random(255);
//              leds[evtPitch << 1] = CHSV(LED_HUE, 255, 255);
//              leds[(evtPitch << 1) + 1] = CHSV(LED_HUE, 255, 255);
              // Set LEDS using potentiometers
              leds[evtPitch << 1] = CHSV(hue_pot, saturation_pot, value_pot);
              leds[(evtPitch << 1) + 1] = CHSV(hue_pot, saturation_pot, value_pot);

            }// Else

          }// If
          else
          {
            // Illegal note
            // Serial.println( "Unknown note" );

          }// else

          break;

        default:
          break;

      }// Switch

      FastLED.show();
#ifdef DEBUG
      sprintf( szStr, "Type: %1X Chan: %d Note: %s Velocity: %d",
               evtType,
               evtChan,
               pitchLUT[evtPitch],
               evtVel );
      Serial.println( szStr );


#endif
      rx = MidiUSB.read();

    } while (rx.header != 0);

  }// If

}// Loop

Many thanks in advance for reading this far and for any help anyone can offer with this.

Mark

Edit to add :
Aggggggghhhhhh!!!!!

Just noticed one of the earth leads had come off the other two pots (they were all ganged together). That would be why they were reading fine with an ohmeter but then giving the wrong value as they were all just floating high!!

Head bowed down while going off to fetch soldering iron!!!


Hmm why does that always happen?!!!

After posting my brain thought why haven't I checked the voltage coming off the pots to see if it's changing!!?

I checked pot 1 the hue pot and sure enough the value of that one is changing from 0-5 volts. The other two pots values are stuck at 5 volts though and not changing. I can't for the life of me see why though as I'm fairly positive their resistance reading is changing so need to figure out what I've got wrong with that part and then hopefully get it all back up and running again.

I can't for the life of me see why the resistance would change but not the voltage coming out though? Surely the two are directly linked to one another?

Thanks,

Mark

Only if you measure the resistance of the pot with all power off, and the wire from the pot wiper to the analogue pin makes proper contact.

Are you using a solderless bread board? These contacts can corrode or work loose over time.

1 Like

Apologies. Reply above as to what happened.

The ground lead had come off the connection from the second and third pots to the first one! Have been looking at this thing for ages and it had gotten hidden under another part of the project so didn't see it.

Must remember to check all connections properly next time!!!

Would still love it if someone could help me with getting the pot values only to spit out to the serial monitor if they've changed since the last time read though if that's possible?

Many thanks,

Mark

Indeed - and remember that not all problems are software problems.

Also check at the input pin to the ADC - to confirm that the signal is actually getting to it.

As @Grumpy_Mike said, solderless breadboards are notorious for poor connections.

Have a static variable to record the 'previous' value, then only print when 'current' != 'previous'.
Update the 'previous' whenever you do a print.

Rather than just "not equal", you might want to use "differs by more than X" ...

Definitely my mistake. The ground had come off the connection between pots 2 and 3! I feel like such an idiot now! Just couldn't see the lead anywhere and my brain was saying it was all there and correct.

Only thing I'd like to do now is change the code so that the hue, saturation and value (brightness) serial prints only print if the value has changed each time in the loop as I can't stop the serial monitor from autoscrolling :frowning:

Yep I've tried that sort of thing and know in my brain what the loop code should look like in its simplest form but getting that into code just isn't working as it won't compile so I know I'm doing something silly somewhere.

Yes it is possible, and quite simple actually.

Just keep a note of the last reading from the pot in a variable or array if you have lots of pots, that is before you map them to the final values to send to MIDI.
Then apply this:-

if( abs(currentPotValue - lastPotValue) > movementThreshold {
// send pot value
lastPotValue = currentPotValue; 
}

As you always get +/- 1 bit variation in analogue make the threshold at least 2 or more.

1 Like

Show the code, and the error(s) you're getting.

Thank you so much everybody for all the help.

This is probably the messiest code in the history of code but it works and does exactly what I need it to so thank you so much!

/*
   MIDIUSB_test.ino

   Created: 4/6/2015 10:47:08 AM
   Author: gurbrinder grewal
   Modified by Arduino LLC (2015)
*/

// a lookup table to convert pitch to text
const char pitchLUT[][4] =
{
  " A0", "B0b", " B0", " C1", "D1b", " D1", "E1b", " E1", " F1", "G1b",
  " G1", "A1b", " A1", "B1b", " B1", " C2", "D2b", " D2", "E2b", " E2",
  " F2", "G2b", " G2", "A2b", " A2", "B2b", " B2", " C3", "D3b", " D3",
  "E3b", " E3", " F3", "G3b", " G3", "A3b", " A3", "B3b", " B3", " C4",
  "D4b", " D4", " E4b", " E4", " F4", "G4b", " G4", "A4b", "A4", "B4b",
  " B4", " C5", "D5b", " D5", "E5b", " E5", " F5", "G5b", " G5", "A5b",
  " A5", "B5b", " B5", " C6", "D6b", " D6", "E6b", " E6", " F6", "G6b",
  " G6", "A6b", " A6", "B6b", " B6", " C7", "D7b", " D7", "E7b", " E7",
  " F7", "G7b", " G7", "A7b", " A7", "B7b", " B7", " C8",
};

#include "MIDIUSB.h"
#include "FastLED.h"
#define DEBUG                   1             // Comment out to stop verbose serial messages
#define DATA_PIN                3             // Output Pin to Data Line on Strip
#define COLOR_ORDER             GRB           // I had to change this for my strip if your color is off then you know.
#define NUM_LEDS                176           // # of LEDS in the strip
#define BRIGHTNESS              220            // Maximum brightness of LEDs
#define LED_TYPE                WS2812B       // WS2812B or WS2811 or whatever
#define MAX_POWER_MILLIAMPS     4000          // Max power draw that LED strip can pull
#define HUE_POT_PIN             A0            // Pin that Pot is attached to for setting LED hue
#define SATURATION_POT_PIN      A1            // Pin that Pot is attached to for setting LED saturation
#define VALUE_POT_PIN           A2            // Pin that Pot is attached to for setting LED value (brightness)

CRGB leds[NUM_LEDS];




uint8_t
evtCIN,
evtType,
evtChan,
evtPitch,
evtVel,
pitch;
char
szStr[40];

uint8_t lastHuePotValue;
uint8_t lastSaturationPotValue;
uint8_t lastValuePotValue;


void setup()
{
  // Sanity check delay - allows reprogramming if accidently blowing power w/leds
  delay(2000);
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
  FastLED.setMaxPowerInVoltsAndMilliamps( 5, MAX_POWER_MILLIAMPS);
  FastLED.setBrightness(BRIGHTNESS);
  FastLED.clear();
  Serial.begin(115200);
}





void loop()

{

  // Read our HUE potentiometer (A0) input and set a variable hue_pot to be used below
  uint16_t huePotRead = analogRead(HUE_POT_PIN);
  uint8_t hue_pot = map(huePotRead, 0, 1023, 0, 255);
  // Serial.print( "Hue = ");
  // Serial.println( hue_pot );

  if( abs(hue_pot != lastHuePotValue)) {
  // send pot value
  lastHuePotValue = hue_pot;
  Serial.print("Hue = ");
  Serial.println(hue_pot);
  }

  // Read our SATURATION potentiometer (A1) input and set a variable saturation_pot to be used below
  uint16_t saturationPotRead = analogRead(SATURATION_POT_PIN);
  uint8_t saturation_pot = map(saturationPotRead, 0, 1023, 0, 255);
  // Serial.print( "Saturation = ");  
  // Serial.println( saturation_pot );
  if( abs(saturation_pot != lastSaturationPotValue)) {
  // send pot value
  lastSaturationPotValue = saturation_pot;
  Serial.print("Saturation = ");
  Serial.println(saturation_pot);
  }

  // Read our VALUE potentiometer (A2) input and set a variable value_pot to be used below
  uint16_t valuePotRead = analogRead(VALUE_POT_PIN);
  uint8_t value_pot = map(valuePotRead, 0, 1023, 0, 255);
  // Serial.print( "Value = ");  
  // Serial.println( value_pot );
  if( abs(value_pot != lastValuePotValue)) {
  // send pot value
  lastValuePotValue = value_pot;
  Serial.print("Brightness = ");
  Serial.println(value_pot);
  }

   // Fade all LEDs down by 1 in brightness each time this is called
//   fadeToBlackBy(leds, NUM_LEDS-1, 10);
//   FastLED.show();

  midiEventPacket_t rx = MidiUSB.read();
  if ( rx.header != 0 )
  {
    do
    {
#ifdef DEBUG
      sprintf( szStr, "Packet: %02X - %02X - %02X - %02X",
               rx.header,
               rx.byte1,
               rx.byte2,
               rx.byte3 );
      // Serial.println( szStr );
#endif
      evtCIN = rx.header & 0xf;
      evtType = (rx.byte1 >> 4) & 0xf;
      evtChan = rx.byte1 & 0xf;
      evtPitch = rx.byte2;
      evtVel = rx.byte3;
      switch ( evtCIN )
      {
        case    0x8:
        case    0x9:
          if ( evtPitch >= 21 && evtPitch <= 108 )
          {
            evtPitch -= 21;
            if ( evtType == 0x8 || (evtType == 0x9 && evtVel == 0) )
            {
              leds[evtPitch << 1] = CRGB::Black;
              leds[(evtPitch << 1) + 1] = CRGB::Black;
              // Fade all LEDs down by 1 in brightness each time this is called
//              leds[evtPitch << 1].fadeToBlackBy(0);
//              leds[(evtPitch << 1) + 1].fadeToBlackBy(0);
            }
            else
            {
              // LED Brightness set depending upon velocity key is played at!
              //leds[evtPitch << 1] = CHSV(150, 255, evtVel*2);
              //leds[(evtPitch << 1) + 1] = CHSV(150, 255, evtVel*2);
              // Standard way of setting LEDs using CHSV
//              int LED_HUE = random(255);
//              leds[evtPitch << 1] = CHSV(LED_HUE, 255, 255);
//              leds[(evtPitch << 1) + 1] = CHSV(LED_HUE, 255, 255);
              // Set LEDS using potentiometers
              leds[evtPitch << 1] = CHSV(hue_pot, saturation_pot, value_pot);
              leds[(evtPitch << 1) + 1] = CHSV(hue_pot, saturation_pot, value_pot);

            }// Else

          }// If
          else
          {
            // Illegal note
            // Serial.println( "Unknown note" );

          }// else

          break;

        default:
          break;

      }// Switch

      FastLED.show();
#ifdef DEBUG
      sprintf( szStr, "Type: %1X Chan: %d Note: %s Velocity: %d",
               evtType,
               evtChan,
               pitchLUT[evtPitch],
               evtVel );
      Serial.println( szStr );

//      Serial.print( "Hue = ");  
//      Serial.println( hue_pot );
//      Serial.print( "Saturation = ");  
//      Serial.println( saturation_pot );
//      Serial.print( "Value = ");  
//      Serial.println( value_pot );

#endif
      rx = MidiUSB.read();

    } while (rx.header != 0);

  }// If

}// Loop

I don't have the first clue with arrays unfortunately and I literally only know enough code to be seriously dangerous :smiley: so just happy I can see the values changing now!!

Many thanks guys.

Out of interest (as I didn't use it and can definitely see how it would be handy to have) how would I go about coding in that movementThreshold?

I did try adding in :

uint8_t movementThreshold = "5";

under where the pot variables are created and also then changing the if statements to this sort of thing :

  if( abs(hue_pot - lastHuePotValue) > movementThreshold) {
  // send pot value
  lastHuePotValue = hue_pot;
  Serial.print("Hue = ");
  Serial.println(hue_pot);
  }

but that's not working for some reason?

Thanks,

Mark

Oh crikey!!!

I had inverted commas around the movementThreshold number. I'm taking it that made it a text value instead of a number?

Taking those inverted commas out seemed to do the trick!!

1 Like

Indeed (although, inside a computer, everything is a number - it just wasn't the number you needed).

This is where you should do something with the pot value. It was inserted so that you knew what to do here, but you misunderstood. I expected you to insert code that actually sent out the code. Otherwise despite it appearing to add a threshold in your print statements, it is not affecting the number of times you are sending out a message unnecessarily.

But if you are happy with what is does then fine.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.