Controlling an array with analog input

Hello, I've started a similar post to this about a sequencing issue that I'm trying to solve. However I'm finding no joy with it so here goes with another question!
Can I set up an array, for example: int mynotes[] = {100,120,140,160,180,200,220,240}; and access any one of these values with a pot connected to analog in? Must there be some form of mapping involved?
I have this piece of code working

 if (digitalRead (DigitalInSwitch0) == HIGH)
      
  {
    val = analogRead(AnalogInFrequency);
    val = map(val, 0, 1023, 100, 240);

    steps[0] = val;
    lastPushedStep = 1;
  }

but of course it gives me every value between 100 and 240!
What I need is to be able to continually select one of these {100,120,140,160,180,200,220,240} I'm tinkering about with it but with no success. Thanks for any ideas :slight_smile:

Just tinkering along with you :slight_smile:

Why not use a case/switch command that reads the value (val) and if it has a certain value it select an value out of your array.

For example if your val has a value of 100 select mynotes[0], this will be 100.

/me

It appears that you want to divide the pot range into 8 discrete sections, so that 0 to 127 means 0, 128 to 255 means 1, 256 to 383 means 2, etc.

Then you want to use 0, 1, 2, etc. as indexes into an array of values.

If that's the case, use

val = map(val, 0, 1024, 0, 8);

Then, use val as an index into the array.

The map function needs to have 1 added to the end of each range because it uses integer arithmetic to compute the return value. If the input range was 0 to 1023 and the output range was 0 to 7, the only input value that would produce an output of 7 would be 1023, and that's not good for your purpose. By adding 1 to each range, the only input value that can produce an output of 8 is 1024, which is not a possible output from analogRead, so it is not a possible output of the map function.

Ok! I think I get it now! Thanks PaulS! My only problem now is how to write the code to access the array. Could you please give me an example of how I connect the mapping to the array? Thanks :slight_smile:

I have thisint val1[] = {100,120,140,160,180,200,220,240};
and I have

 {
    val = analogRead(AnalogInFrequency);
    val = map(val, 0, 1024, 0, 8);

    steps[0] = val1;
    lastPushedStep = 1;
  }

but I don't see how they can connect. As you can tell, I'm a complete eejit!!

int mynotes[] = {100,120,140,160,180,200,220,240};

void loop()
{
  int val = analogRead((AnalogInFrequency);
  int index = map(val, 0, 1024, 0, 8);

  int myNote = mynotes[index];
  // Play me myNote
}

Sorry! I spoke to soon! Now to run away and try it! Thanks a million sir :slight_smile:

As you can tell, I'm a complete eejit!!

I like one of the member's tag lines that says "I'm not a complete idiot. Some parts are missing".

That indeed is a positive spin!

I'm afraid I have all the parts! ;D

I don't think this is working with the existing code though. Could I trouble you to have a quick look paulS? Each switch when activated needs to access that array. Maybe the code needs to be reworked in order to fit your solution? This is the original code I'm tinkering with. Basically when I press one of the switches within the sequence I toggle the frequency pot until I release the switch. But of course now I'm trying to access a particular value in the array :slight_smile:

/* ======================================================================
 Arduino Punk Console
 A simple programmable 8 step tone sequencer 
 by dano/beavisaudio.com

 Revs
 -----------------------------------
 15 Sept  djh  initial version
======================================================================*/

// Map all the input and output pins
#define AnalogInFrequency 1
#define AnalogInTempo 2
#define AnalogInDuration 0
#define DigitalOutSignal 11
#define DigitalInSwitch0 2
#define DigitalInSwitch1 3
#define DigitalInSwitch2 4
#define DigitalInSwitch3 5
#define DigitalInSwitch4 6
#define DigitalInSwitch5 7
#define DigitalInSwitch6 8
#define DigitalInSwitch7 9 
#define DigitalInStartStop 10
#define DigitalOutLED 12

// Set up the array for each step
int steps[] = {100,120,140,160,180,200,220,240};

// misc housekeeping
int duration = 50;
int pitchval = 1;
int fPlayMode = true;
int lastPushedStep = -1;

// Initialize the tempo
int tempo = 100;

void setup()
{ 
  // setup pin modes (Digital pins are input by default, but
  // I like to set 'em explicitly just so the code is clear.
  pinMode (DigitalInSwitch0, INPUT);
  pinMode (DigitalInSwitch1, INPUT);
  pinMode (DigitalInSwitch2, INPUT);
  pinMode (DigitalInSwitch3, INPUT);
  pinMode (DigitalInSwitch4, INPUT);
  pinMode (DigitalInSwitch5, INPUT);
  pinMode (DigitalInSwitch6, INPUT);
  pinMode (DigitalInSwitch7, INPUT);                
  pinMode (DigitalInStartStop, INPUT);
  pinMode (DigitalOutSignal, OUTPUT);  
  pinMode (DigitalOutLED, OUTPUT);

  // setup comms for the LCD display
  Serial.begin(9600);

  StartupMessage();

} 

void StartupMessage()
{
  clearLCD();
  Serial.print ("BEAVIS: Arduino");
  delay(300);
  Serial.print (254, BYTE);
  Serial.print (192, BYTE);
  Serial.print ("Punk Console!");
  delay (2000);
  clearLCD();
  Serial.print ("Beavis: APC");
}

void clearLCD()
{
  Serial.print(254, BYTE);
  Serial.print(1, BYTE);
}

void loop() 
{
  // Main sequence loop  
  for (int i=0; i<8; i++)
  {   
    // Are we playing or stopping?
    fPlayMode = digitalRead (DigitalInStartStop);
    digitalWrite (DigitalOutLED, HIGH);

    // Check the Hardware
     readSwitches();
     readPots();

    // update the display
    updateDisplay();

    // Make the noise
    if (fPlayMode)
    {
      freqout (steps[i], duration);
    }
    digitalWrite (DigitalOutLED, LOW);

    // Pause between steps
    delay (tempo);       
  }
} 


void updateDisplay()
{
  Serial.print (254, BYTE);
  Serial.print (192, BYTE);
  Serial.print ("T:");
  Serial.print (tempo);
  Serial.print (" d:");
  Serial.print (duration);

 if (lastPushedStep != -1)
 {
    Serial.print ("*");
    Serial.print (lastPushedStep);
 }
}

// Read the current values of the pots, called from the loop.
void readPots ()
{
    tempo = (analogRead (AnalogInTempo) * 1.9);
    duration = (analogRead (AnalogInDuration));      
}

// Read the current values of the switches and
// if pressed, replace the switch's slot frequency
// by reading the frequency pot.
void readSwitches()
{
  // reset last pushed button number
  lastPushedStep = -1;

  // check switch 0, if pressed, get the current freq into step 0, etc. etc.
  if (digitalRead (DigitalInSwitch0) == HIGH)
  {
    steps[0] = analogRead(AnalogInFrequency);
    lastPushedStep = 1;
  }

  else if (digitalRead (DigitalInSwitch1) == HIGH)
  {
    steps[1] = analogRead(AnalogInFrequency);
    lastPushedStep = 2;
  }

  else if (digitalRead (DigitalInSwitch2) == HIGH)
  {
    steps[2] = analogRead(AnalogInFrequency);
    lastPushedStep = 3;
  }
  else if (digitalRead (DigitalInSwitch3) == HIGH)
  {
    steps[3] = analogRead(AnalogInFrequency);
    lastPushedStep = 4;
  }
  else if (digitalRead (DigitalInSwitch4) == HIGH)
  {
    steps[4] = analogRead(AnalogInFrequency);
    lastPushedStep = 5;
  }
  else if (digitalRead (DigitalInSwitch5) == HIGH)
  {
    steps[5] = analogRead(AnalogInFrequency);
    lastPushedStep = 6;
  }
  else if (digitalRead (DigitalInSwitch6) == HIGH)
  {
    steps[6] = analogRead(AnalogInFrequency);
    lastPushedStep = 7;
  }
  else if (digitalRead (DigitalInSwitch7) == HIGH)
  { 
    steps[7] = analogRead(AnalogInFrequency);
    lastPushedStep = 8;
  }
}


//freqout code by Paul Badger 
// freq - frequency value
// t - time duration of tone
void freqout(int freq, int t) 
{ 
  int hperiod;     //calculate 1/2 period in us 
  long cycles, i; 

  // subtract 7 us to make up for digitalWrite overhead - determined empirically 
  hperiod = (500000 / ((freq - 7) * pitchval));             

  // calculate cycles 
  cycles = ((long)freq * (long)t) / 1000;    // calculate cycles 

  for (i=0; i<= cycles; i++)
  {              // play note for t ms  
    digitalWrite(DigitalOutSignal, HIGH);  
    delayMicroseconds(hperiod); 
    digitalWrite(DigitalOutSignal, LOW);  
    delayMicroseconds(hperiod - 1);     // - 1 to make up for fractional microsecond in digitaWrite overhead 
  } 
}

:slight_smile: I think I did it!! I mightn't be complete after all :slight_smile:

Ok, so that works now :slight_smile: Thanks for pulling me out of a tight spot paulS. Here's the code for anyone that wants it

/* ======================================================================
 Arduino Punk Console
 A simple programmable 8 step tone sequencer 
 by dano/beavisaudio.com

 Revs
 -----------------------------------
 15 Sept  djh  initial version
======================================================================*/

// Map all the input and output pins
#define AnalogInFrequency 1
#define AnalogInTempo 2
#define AnalogInDuration 0
#define DigitalOutSignal 11
#define DigitalInSwitch0 2
#define DigitalInSwitch1 3
#define DigitalInSwitch2 4
#define DigitalInSwitch3 5
#define DigitalInSwitch4 6
#define DigitalInSwitch5 7
#define DigitalInSwitch6 8
#define DigitalInSwitch7 9 
#define DigitalInStartStop 10
#define DigitalOutLED 12

// Set up the array for each step
int steps[] = {90,106,118,139,155,173,204,228};

int val = analogRead(AnalogInFrequency);
int mynotes[] = {90,106,118,139,155,173,204,228,};




// misc housekeeping
int duration = 50;
int pitchval = 1;
int fPlayMode = true;
int lastPushedStep = -1;

// Initialize the tempo
int tempo = 100;

void setup()
{ 
  // setup pin modes (Digital pins are input by default, but
  // I like to set 'em explicitly just so the code is clear.
  pinMode (DigitalInSwitch0, INPUT);
  pinMode (DigitalInSwitch1, INPUT);
  pinMode (DigitalInSwitch2, INPUT);
  pinMode (DigitalInSwitch3, INPUT);
  pinMode (DigitalInSwitch4, INPUT);
  pinMode (DigitalInSwitch5, INPUT);
  pinMode (DigitalInSwitch6, INPUT);
  pinMode (DigitalInSwitch7, INPUT);                
  pinMode (DigitalInStartStop, INPUT);
  pinMode (DigitalOutSignal, OUTPUT);  
  pinMode (DigitalOutLED, OUTPUT);

  // setup comms for the LCD display
  Serial.begin(9600);

  StartupMessage();

} 

void StartupMessage()
{
  clearLCD();
  Serial.print ("BEAVIS: Arduino");
  delay(300);
  Serial.print (254, BYTE);
  Serial.print (192, BYTE);
  Serial.print ("Punk Console!");
  delay (2000);
  clearLCD();
  Serial.print ("Beavis: APC");
}

void clearLCD()
{
  Serial.print(254, BYTE);
  Serial.print(1, BYTE);
}

void loop() 
{
  // Main sequence loop  
  for (int i=0; i<8; i++)


  {   
    // Are we playing or stopping?
    fPlayMode = digitalRead (DigitalInStartStop);
    digitalWrite (DigitalOutLED, HIGH);

    // Check the Hardware
     readSwitches();
     readPots();

    // update the display
    updateDisplay();

    // Make the noise
    if (fPlayMode)
    {
      freqout (steps[i], duration);
    }
    digitalWrite (DigitalOutLED, LOW);

    // Pause between steps
    delay (tempo);       
  }
} 


void updateDisplay()
{
  Serial.print (254, BYTE);
  Serial.print (192, BYTE);
  Serial.print ("T:");
  Serial.print (tempo);
  Serial.print (" d:");
  Serial.print (duration);

 if (lastPushedStep != -1)
 {
    Serial.print ("*");
    Serial.print (lastPushedStep);
 }
}

// Read the current values of the pots, called from the loop.
void readPots ()
{
    tempo = (analogRead (AnalogInTempo) * 1.9);
    duration = (analogRead (AnalogInDuration));      
}

// Read the current values of the switches and
// if pressed, replace the switch's slot frequency
// by reading the frequency pot.
void readSwitches()

{
  // reset last pushed button number
  lastPushedStep = -1;

  // check switch 0, if pressed, get the current freq into step 0, etc. etc.
  if (digitalRead (DigitalInSwitch0) == HIGH)
      
  {
    int val = analogRead(AnalogInFrequency);
    int index = map(val, 0, 1024, 0, 8);
    int myNote = mynotes[index];
     steps[0] = myNote;
     lastPushedStep = 1;
  }

  else if (digitalRead (DigitalInSwitch1) == HIGH)
  { 
    int val = analogRead(AnalogInFrequency);
    int index = map(val, 0, 1024, 0, 8);
    int myNote = mynotes[index];
     steps[1] = myNote;
     lastPushedStep = 2;
  }

  else if (digitalRead (DigitalInSwitch2) == HIGH)
  { 
    int val = analogRead(AnalogInFrequency);
    int index = map(val, 0, 1024, 0, 8);
    int myNote = mynotes[index];
     steps[2] = myNote;
     lastPushedStep = 3;
  }
  else if (digitalRead (DigitalInSwitch3) == HIGH)
  { 
    int val = analogRead(AnalogInFrequency);
    int index = map(val, 0, 1024, 0, 8);
    int myNote = mynotes[index];
     steps[3] = myNote;
     lastPushedStep = 4;
  }
  else if (digitalRead (DigitalInSwitch4) == HIGH)
  { 
    int val = analogRead(AnalogInFrequency);
    int index = map(val, 0, 1024, 0, 8);
    int myNote = mynotes[index];
    steps[4] = myNote;
    lastPushedStep = 5;
  }
  else if (digitalRead (DigitalInSwitch5) == HIGH)
  { 
    int val = analogRead(AnalogInFrequency);
    int index = map(val, 0, 1024, 0, 8);
    int myNote = mynotes[index];
    steps[5] = myNote;
    lastPushedStep = 6;
  }
  else if (digitalRead (DigitalInSwitch6) == HIGH)
  { 
    int val = analogRead(AnalogInFrequency);
    int index = map(val, 0, 1024, 0, 8);
    int myNote = mynotes[index];
    steps[6] = myNote;
    lastPushedStep = 7;
  }
  else if (digitalRead (DigitalInSwitch7) == HIGH)
  { 
int val = analogRead(AnalogInFrequency);
    int index = map(val, 0, 1024, 0, 8);
    int myNote = mynotes[index];

    steps[7] = myNote;
    lastPushedStep = 8;
  }
}


//freqout code by Paul Badger 
// freq - frequency value
// t - time duration of tone
void freqout(int freq, int t) 
{ 
  int hperiod;     //calculate 1/2 period in us 
  long cycles, i; 

  // subtract 7 us to make up for digitalWrite overhead - determined empirically 
  hperiod = (500000 / ((freq - 7) * pitchval));             

  // calculate cycles 
  cycles = ((long)freq * (long)t) / 1000;    // calculate cycles 

  for (i=0; i<= cycles; i++)
  {              // play note for t ms  
    digitalWrite(DigitalOutSignal, HIGH);  
    delayMicroseconds(hperiod); 
    digitalWrite(DigitalOutSignal, LOW);  
    delayMicroseconds(hperiod - 1);     // - 1 to make up for fractional microsecond in digitaWrite overhead 
  } 
}

This should be fun to turn into a 16 step sequencer and add some lights as well :slight_smile: Thanks to dano/beavisaudio.com
for this, it's a great project! :slight_smile:

This might help make the program smaller without changing its meaning.

In readSwitches there are lots of blocks which look like:

  if (digitalRead (DigitalInSwitch0) == HIGH)
  {
    int val = analogRead(AnalogInFrequency);
    int index = map(val, 0, 1024, 0, 8);
    int myNote = mynotes[index];
     steps[0] = myNote;
     lastPushedStep = 1;
  }

AFAIK, every block has the same three lines:

    int val = analogRead(AnalogInFrequency);
    int index = map(val, 0, 1024, 0, 8);
    int myNote = mynotes[index];

Move these three common lines to the front of the whole if, like this:

  int val = analogRead(AnalogInFrequency);
  int index = map(val, 0, 1024, 0, 8);
  int myNote = mynotes[index];
  if (digitalRead (DigitalInSwitch0) == HIGH)
  {
     steps[0] = myNote;
     lastPushedStep = 1;
  }
  else if (digitalRead (DigitalInSwitch1) == HIGH)
  {
     steps[1] = myNote;
     lastPushedStep = 2;
  }
...

Once you've done that you'll notice that the code looks almost exactly the same inside the if tests.
look at button N
if button N == HIGH
steps[N] = myNote
lastPushedStep = N+1;

Have a look at using an array to hold the button pin, and look into using a for loop to do the similar code repeatedly. The code will become even more compact, and hopefully remain understandable.

Just some challenges to keep things moving :slight_smile:

HTH
GB
[edit]If the button pin numbers are in an array, this code becomes a for loop too:

  pinMode (DigitalInSwitch0, INPUT);
  pinMode (DigitalInSwitch1, INPUT);
  pinMode (DigitalInSwitch2, INPUT);
  pinMode (DigitalInSwitch3, INPUT);
  pinMode (DigitalInSwitch4, INPUT);
  pinMode (DigitalInSwitch5, INPUT);
  pinMode (DigitalInSwitch6, INPUT);
  pinMode (DigitalInSwitch7, INPUT);

[/edit]

Are you saying I must replace this part

if (digitalRead (DigitalInSwitch0) == HIGH)
  {
     steps[0] = myNote;
     lastPushedStep = 1;
  }

with this?

  int N;
  if ( digitalRead (N) == HIGH)
  
  {
    
     steps[N] = myNote;
     lastPushedStep = N+1;
  }

and then use this for an array?int N[] = {0,1,2,3,4,5,6,7}; and if I look into using a "for" loop most of this will be replaced? Sorry to seem dumb but I don't know my If's from me For's ;D Ok, i'm going to try that out and see what happens :slight_smile:

"N" can't be an "int" and an array of "int"s.

Think of an array as a set of houses on a street, each with an address.
The address of the house is not the same as the contents of the house.

So:

int house [4] = {12, 25, 32, 0};

So, at house zero lives the number 12 and at house 3 lives the number zero.

Does that help?

just realized that! Thanks AWOL :slight_smile:

Thanks AWOL :slight_smile: I understand that now but I don't really understand what gbulmer means by

look at button N
if button N == HIGH
steps[N] = myNote
lastPushedStep = N+1;

am I to try modifying this in order to replace

if (digitalRead (DigitalInSwitch0) == HIGH)
  {
     steps[0] = myNote;
     lastPushedStep = 1;
  }

oh boy!

How about if I wrote it:

look at button N
if button [N] == HIGH
steps[N] = myNote
lastPushedStep = N+1

look at button N
if button[glow] [N][/glow] == HIGH
  steps[N] = myNote
  lastPushedStep = N+1

The difference I see is that you have the xtra [] around the first N and no ; at the end! Did I pass? :slight_smile:

I don't mean to be smart!! Just wish I was! :slight_smile: