how to create an array with both members and number of members undefined

I was so curious that even though my head is about to explode tonight I simply had to check -
unfortunately it doesn't work. Freemode works, record is unknown to me at this stage simply because Play/Rewind and all the rest do not work...
BUT as I stated before - I need to get my head around this and figure the technique and then use fix the code to fit my needs.

So once again - thanks a bunch...

Hey Rob - 2 questions if it's not a bother:

1/ in your code you write the free mode code without a loop, and it still works continually.
Does that actually mean that a case will run within itself until another case is happening and only then will it "break"?

2/ What did you mean by this remark:
val = map(val, 0, 1023, 0, 179); // val = val * 45/256; //val stays just within an unsigned int. <==> val * 180/1024

As for the "blink without delay" remark - thanks! I'm putting it in!

  1. as long as the mode == FREE that part of the switch statement will be executed. If you are not familiar with the switch statement it is like a long list of

if (mode == FREE) ...
else if (mode == RECORD) ...
else if ... etc

do a case will execute lines until it encounters the break; and then it will leave the switch statement. Then it will loop again assuming mode has not changed it will switch to the right mode part again until you send a command that changes the mode.

  1. I mean the formula val = map (val, 0, 1023, 0, 179) can be simplified to val = val * 45/256; if val is an unsigned int. But that is just a small optimization not needed imho.

If you get this thing wrking you should consider adding the time dimension to the code so if the servo rotates to 45 and stay there for a minute and tehn to 90 and stay there for 10 seconds, the replay should do the same.. And try to implement this in the form (duration, position) pairs. Good exercise and would greatly increment the length of the recording as now it will record 500 positions, then it will record 500 different positions.

Finally the recordArray can be of type uint8_t as it only stores a value between 0..179 :slight_smile:

Rob, once again you're patient and explaining, thank you very much!

BTW, you last remark "Finally the recordArray can be of type uint8_t as it only stores a value between 0..179 "
was meant to be unsigned int, right?

BTW, you last remark "Finally the recordArray can be of type uint8_t as it only stores a value between 0..179 "
was meant to be unsigned int, right?

No, he meant what he said. That range of values will fit in a single byte - no need to waste space using int.

Another name for uint8_t is byte.

Aha!
Thanks GoForSmoke.

Hey guys - now it works! :smiley:

I had to rewrite some, and add a mode in order to preserve an int called "firstidx" - I suppose there could be a better/more professional way...
Rob - the "fast forward" mode is not needed in my setup so it's gone =( ...

It's far from finished. I still need to add the switches (which now I plan on adding just three and toggling) and LEDs.

here's what I have now, for your forgiving consideration :slight_smile:

#define IDLE 0
#define FREE 1
#define RECORD 2
#define PLAYBACK 3
#define STOP 4
#define REWIND 5
#define RECORDCONT 6

int mode = IDLE;
int idx, lastidx, firstidx;
int maxidx = 500;

#include <Servo.h> 

Servo myservo;                                 // create servo object to control a servo 
char buffer [5];                                 //variable to hold keystrokes
int potpin = 0;                                  // analog pin used to connect the potentiometer
unsigned int val;                           // variable to read the value from the analog pin 
const int valNumber = 500;           //variable to contain number of array members
int incomingByte;                          //declare variable to hold incoming letter
int servoPos[valNumber];            //create array of values for servo position
const int waitForServo = 15;      //delay time to let servo get to position 


int recordModeLed = 3;                  // defining pins for ui leds
int homeModeLed = 4;
int playModeLed = 5;
int freeModeLed = 6;
int freeSwitch = 7;                         //defining pins for switches
int recSwitch = 8;
int homeSwitch = 9;
int playSwitch = 10;

void setup() 
{
  Serial.begin(9600);
  Serial.flush();
  myservo.attach(2);                                                   // attaches the servo on pin 2 to the servo object 
  pinMode (freeModeLed, OUTPUT);                         //defining LED pins as output
  pinMode (recordModeLed, OUTPUT);
  pinMode (homeModeLed, OUTPUT);
  pinMode (playModeLed, OUTPUT);
  pinMode (freeSwitch, INPUT);                              //defining switch pins as input
  pinMode (recSwitch, INPUT);
  pinMode (homeSwitch, INPUT);
  pinMode (playSwitch, INPUT);
}


void loop ()
{
  digitalWrite (freeModeLed, LOW);
  digitalWrite (recordModeLed, LOW);
  digitalWrite (homeModeLed, LOW);
  digitalWrite (playModeLed, LOW);

  // HANDLE IO

  if (Serial.available( ) > 0) 
  {
    incomingByte = Serial.read ( );

    switch(incomingByte)
    {
    case 'f': 
      mode = FREE; 
      Serial.println ("Free mode");  
      break;
    case 'r': 
      mode = RECORD; 
      Serial.println ("Record");
      break;
    case 's' : 
      mode = STOP; 
      Serial.println ("STOP");
      break;
    case 'w' : 
      mode = REWIND; 
      Serial.println ("Rewind");
      break;
    case 'p': 
      mode = PLAYBACK; 
      Serial.println ("Playback");
      break;
    case 'i': 
      mode = IDLE; 
      break;
    }
  }

  switch(mode)
  {
  case IDLE:  // do nothing
    break;

  case FREE:
    digitalWrite (freeModeLed, HIGH);
    val = analogRead (potpin);
    val = map(val, 0, 1023, 0, 179);                   // val = val * 45/256; // <==> val * 180/1024
    myservo.write (val);
    Serial.println (val);
    delay (waitForServo);                           //  should be refactored away -> like blink without delay
    break;

  case RECORD:

    digitalWrite (recordModeLed, HIGH);
    Serial.println ("Record function");         // if so - prints record
    val = analogRead(potpin);                              // reads the value of the potentiometer (value between 0 and 1023) 
    val = map(val, 0, 1023, 0, 179);                              // scale it to use it with the servo (value between 0 and 180) 
    myservo.write(val);                                          // sets the servo position according to the scaled value 
    servoPos [idx]=val;                                          // stores val in array "servoPos
    firstidx = idx;
    mode = RECORDCONT;

    break;

  case RECORDCONT:

    val = analogRead(potpin);                             // reads the value of the potentiometer (value between 0 and 1023) 
    val = map(val, 0, 1023, 0, 179);                             // scale it to use it with the servo (value between 0 and 180) 
    myservo.write(val);                                         // sets the servo position according to the scaled value 
    servoPos [idx]=val;                                         // stores val in array "servoPos
    idx ++ ;
    lastidx = idx;
    if (idx == maxidx) mode = STOP;
    delay(waitForServo);                                      // waits for the servo to get there
    Serial.println(val);                                       // print values for checking

    break;

  case REWIND:

    for (int i=lastidx;i>firstidx;i--)
    {
      myservo.write (servoPos [i]);
      val = servoPos [i];
      delay (waitForServo);
      Serial.println (val);
    }
    mode = STOP;
    break;

  case PLAYBACK:
    for (int i=0; i< lastidx; i++)  
    {
      myservo.write (servoPos[i]);
      val = servoPos [i];
      delay (waitForServo);
      Serial.println (val);
    }
    mode = STOP;
    break;

  }
}

good to see you got it working.

nice rewinder !

there is no case for stop in the switch? is it the same state as idle now?

Why is incomingByte an int?
Or mode? Do you have more than 255 modes?

These should be const bytes, they are small and do not change:

int recordModeLed = 3;                  // defining pins for ui leds
int homeModeLed = 4;
int playModeLed = 5;
int freeModeLed = 6;
int freeSwitch = 7;                         //defining pins for switches
int recSwitch = 8;
int homeSwitch = 9;
int playSwitch = 10;

Thanks guys.
GoForSmoke you are correct and thanks for the remark.

Tom, actually I haven't paid attention to that part (...) and IDLE is indeed no longer needed.

Is there a way for me to now take the array and smooth its curve of values so as to get rid of small jitters?
Do you believe a stepper motor could do a better job of moving smoothly? The servo moves a focus ring on a lens.
Do you think an optical encoder w/high resolution will help that (or maybe the 180 degree resolution of the servo limits me?

Thank you

I'm looking all over the place, and I guess it's just my lack of understanding :~, but I can't find a decent example of a continuous array being smoothed - not just averaged. What I mean is that if in the course of 300 values from 0 to 299 I have parts like:

234, 235, 238, 236, 239, 240, 241

I can smooth the curve to

234, 235, 236, 237, 238, 239, 240

Any pointer?
Thanks

Just sort it?

Look up: qsort

No Nick - I mean smoothing the curve between the values so as to get rid of unwanted jitter

234, 235, 238, 236, 239, 240, 241

I can smooth the curve to

234, 235, 236, 237, 238, 239, 240

should be smoothed to: 234, 235, 236, 238, 239, 240, 241

Nick was in the right direction, with sorting, but instead of sorting the whole array you must sort a small window.
you can use a single pass of bubble sort to remove jitter with a window size of 2 values.
You can create algorithms that do smoothing upon 2,3,4,..100 values that are basicly al the same.

get the idea?

Unfortunately... far from it :blush:
I mean, I understand the idea but not how to take my arrays and do this.
I hate to admit it but the whole "create algorithms" stuff is for me like "write a poem in Chinese"...

Well, do a single pass through the array. If two values are in the wrong order, swap them.

I don't think sorting is the right option. How would it handle decrements? Sounds like what he's looking for is more of a lowpass filter algorithm.

Maybe a good place to start would be to average three values at a time, and set the middle to the average. Consider this sequence:

200 205 210 220 212 214 212 209 199 209 200

There are spikes up at 220 and down at 199. If you wrote a procedure to take (index) and (index + 2) and average them, then write that to (index + 1), you end up with:

200 205 212 212 213 212 210 205 207 203 200

You end up distorting the actual values, but smooth the response considerably. Maybe it's a good trade, maybe it isn't, but it's an easy loop to code:

// Loop from first entry to two-from-last entry
// (Can't use next-to-last or last indexes because i+2 is out of bounds)
for (int i = 0; i < max - 2; i++) {
  array[i + 1] = (array[i] + array[i + 2]) / 2;
}

edit: Ugh, I swear.. I need to learn to proof-read. I've edited this like four times to fix things.

Soffer:
I'm looking all over the place, and I guess it's just my lack of understanding :~, but I can't find a decent example of a continuous array being smoothed - not just averaged. What I mean is that if in the course of 300 values from 0 to 299 I have parts like:

234, 235, 238, 236, 239, 240, 241

I can smooth the curve to

234, 235, 236, 237, 238, 239, 240

Any pointer?
Thanks

You want curve fitting or can you live with a linear fit? That's possibly a major scope in itself.

The quick and easy for curve fitting would be to transfer the data to your PC and use an application there. Perhaps a spreadsheet or matlab?

oohh, seems like I'm stepping into deep water here - for me at least...
Thank you all for replying :slight_smile:

Nick - how do I do what you suggest? I'd be happy to try and see if it works.
SirNickity - I'm going to try and use your suggestion and see what comes at the other side. Thanks.
GoForSmoke - I think linear would suit me fine (and I don't want to use a pc). Does that mean using SirNickity's technique? Or are you talking about some other way of doing this?