Go Down

### Topic: writing an expression for box spiral robot (Read 1 time)previous topic - next topic

#### geoland

##### Jul 31, 2011, 01:33 pmLast Edit: Aug 04, 2011, 08:12 pm by geoland Reason: 1
I want a simple stepper driven robot device to push buttons (cross configuration) on a hand controller, controlling two perpendicular axis. Thinking 2D,  turning right and moving forward only.

An arm attached to the stepper shaft sweeps over the pushbuttons activating them. To move forward two steps the arm sweeps left then right and vice versa. To turn right, the arm sweeps over two adjacent buttons, going clockwise.

The sequence to do this is as follows - where -1 == left sweep and 1 == right sweep. 2 ==  right and right again. The arm travels 90deg with each sweep.

Each sequence is repeated before being incremented and actioned twice - and so on in the following pattern - a box spiral.

2, -1, 2, -1, 2, -1, 1, -1, 2, -1, 1, -1, 2, -1, 1, -1, 1, -1, 2, -1,1,-1,1,-1, 2,...

I am baffled as to how to express this to run as a for or while statement or other expression.

Why am I doing this? Besides moving an imaging sensor between shots to increase signal to noise ratio in the finished image, the instrument is practically a collectors item. It has a +ve earth! And I don't want to affect it cosmetically.

A bit left field, but thanks for looking.

Rowland.

#### wildbill

#1
##### Jul 31, 2011, 03:19 pmLast Edit: Jul 31, 2011, 03:21 pm by wildbill Reason: 1
Could you give a bit more detail about how this works and how that sequence you've provided breaks out into repeated subsequences. I'm struggling to see what it does.

edit: a picture might help

#### Utopia

#2
##### Aug 01, 2011, 10:44 am
This will repeat the sequence you showed:

Code: [Select]
`void doSomethingWithIt(int m){  Serial.println(m);}void sequence(void){  int seq2=1;  while (1)  {    for (int i=0;i<2;++i)    {      doSomethingWithIt(2);      for (int k=0;k<seq2;++k)        doSomethingWithIt( ( k&1 ? 1 : -1 ) );    }    seq2+=2;  }}`

Just replace doSomethingWithIt() internals with your control code.

#### Utopia

#3
##### Aug 01, 2011, 11:15 am
Of course, maybe you want to call a function and get a single value back - here's that:
Code: [Select]
`int sequence2(int reset){  static seq2=-1, i=99, k=99;  if (reset)  {    i = k = 99;    return 0; // dummy value - ignore  }  if (k>=seq2)  {    ++i;    k=-1;  }  if (i>=2)  {    i=0;    k=-1;    seq2+=2;  }  if (k++<0)  {    return 2;  }  return ( k&1 ? -1 : 1 );}`

Every time you call sequence2(0); it will return the next number in your sequence - if you want to restart back at the beginning again, then call it with sequence2(1) once, then continue with sequence2(0) from then on for the sequence

#### geoland

#4
##### Aug 01, 2011, 10:28 pm
Thanks, once again, David. I will look at fitting these options into the existing sketch this week.

Rowland

#### Utopia

#5
##### Aug 03, 2011, 03:04 am

I presume this is what you intended - I couldn't get it to compile otherwise.
...
If I understand the intent of your code. It is the stepping sequence that is controlled in this case with a constant motor speed.

Yes, the functions will need to be put in front so later functions can 'see' them.

The two functions simply take the sequence you listed and calculate them. The first one is an infinite loop, so you may want to consider using the second so you have more control over the sequence. Also, you can see in the code where you pass the 2, 1, and -1 - if you need to change their values, just change those.

#### geoland

#6
##### Aug 03, 2011, 11:35 am
Thanks David.

I get the error;

ISO C++ forbids declaration of 'seq2' with no type -

this is repeated for the values i and k in the same line.

This is how I've implemented your second code, between setup and loop.

Code: [Select]
`void setup() {  pinMode(shutterPin, OUTPUT);  pinMode(mirrorPin, OUTPUT);  pinMode(ledPin, OUTPUT);  Serial.begin(115200);}// dither routine int sequence2(int reset) {  static seq2=-1, i=99, k=99;  if (reset)  {    i = k = 99;    return 0; // dummy value - ignore  }  if (k>=seq2)  {    ++i;    k=-1;  }  if (i>=2)  {    i=0;    k=-1;    seq2+=2;  }  if (k++<0)  {    return 2;  }  return ( k&1 ? -1 : 1 );} void loop() {`

#### Utopia

#7
##### Aug 03, 2011, 12:10 pm

I get the error;
ISO C++ forbids declaration of 'seq2' with no type -
this is repeated for the values i and k in the same line.

Sorry - change

Code: [Select]
`static seq2=-1, i=99, k=99;`

to

Code: [Select]
`static int seq2=-1, i=99, k=99;`

The compiler I used to test on allows implied int there, but the (better) Arduino compiler rightly complains about it.

#### geoland

#8
##### Aug 18, 2011, 01:51 pm
I have set up the spiral pattern as below - frame count calling steps0, steps1... etc by  if() statements. The stepper rotates and pushes a button as it goes, stops and pushes the next button, either forward or reverse to trace out the box spiral. A bit clunky, but eminently easier for a newbie. I've implemented a wake up delay and hardware switch inputs for pause and stop along with an automatic stop after the desired number of frames is complete.

It was easier to do it this way and have control over image number instead of using a session time that had to be calculated based on image count anyway. The user can input the desired number of images and exposure time and wake up and the session time is calculated automatically and accurately.

The only issue is that 100 frames is 300 lines of code? Only 40 at the moment. This is pretty much finished for now and ready to go into production.

Code: [Select]
`#include <Stepper.h>/* Ditherbot/Sparehand.Rowland Cheshire 2011 This sketch automates multiple long exposure with a Canon DSLR Camera and includes a stepper driven dithering mechanism to press 4 pushbutton switches on a hand controller. Dithering, is moving the camera sensor between shots so that subsequent images does not fall on the same pixels, which improves final image quality. The camera will be mounted on an equatorial mount with the Ditherbot/Sparehand repositioning in RA and DEC between exposures. The image sequencing and dithering is independent of equatorial mount electronics which is '+ve' earth. Written for a bipolar/unipolar stepper motor - some rewriting will be needed for 3 wire variable reluctance motors - CDROM drives */// Variables - set next 3 lines as required// set number of images#define images 40// set exposure timeunsigned long exposure_tm = 420000; //default// set wake up timeunsigned long wake_tm = 300000; //default/* generally fixed variables - set and forget */# define pre_shutter 100#define mirror_delay 2900#define predither_tm 2000#define interval_tm 2000#define motor_delay 3000#define motorSteps 200 #define motorspeed 5// comment out boolean statement and substitute with milliseconds if desiredunsigned long session_tm = ((exposure_tm + mirror_delay + predither_tm + motor_delay + interval_tm + pre_shutter)*images) + wake_tm;/* fixed - no changes */#define image_session images#define pin2 2#define pin3 3#define shutter_pin 8#define focus_pin 11 // to be implemented - manual focus#define led_pin 13int pinval2;int pinval3;int frames = 0;int steps;long time = millis();/* stepper motor - dither sequence */#define motorPin1 4#define motorPin2 5#define motorPin3 6#define motorPin4 7Stepper stepper(motorSteps, motorPin1,motorPin2,motorPin3,motorPin4);/* dither pattern - call these lines sequentially */#define steps0 50#define steps1 50#define steps2 -50#define steps3 50#define steps4 50#define steps5 -50#define steps6 50#define steps7 50#define steps8 -50#define steps9 50#define steps10 -50#define steps11 50#define steps12 50#define steps13 -50#define steps14 50#define steps15 -50#define steps16 50#define steps17 50#define steps18 -50#define steps19 50#define steps20 -50#define steps21 50#define steps22 -50#define steps23 50#define steps24 50#define steps25 -50#define steps26 50#define steps27 -50#define steps28 50#define steps29 -50#define steps30 50#define steps31 50#define steps32 -50#define steps33 50#define steps34 -50#define steps35 50#define steps36 -50#define steps37 50#define steps38 -50#define steps39 50/* focus is manual for this application will implement with hardware switch on/off */// void sequences start here/* this is the automated image capture dithering cycle. Session end is automatic for session time and 40 frames or pause and user end session */// exposurevoid cycle() {  // mirror lock up  digitalWrite(shutter_pin, HIGH);  delay(pre_shutter);  // reset camera_pin LOW, ready to fire shutter  digitalWrite(shutter_pin, LOW);  // hold open for 3 seconds  delay(mirror_delay);  // add focus here pin 11  // press 2 - fire shutter  digitalWrite(shutter_pin, HIGH);  delay(exposure_tm);  // close shutter  digitalWrite(shutter_pin, LOW);  delay(predither_tm);  // dithering  digitalWrite(led_pin, HIGH);   frames++;  Serial.println(frames);  if (frames == 1)    steps = steps0;  if (frames == 2)    steps = steps1;  if (frames == 3)    steps = steps2;  if (frames == 4)    steps = steps3;  if (frames == 5)    steps = steps4;  if (frames == 6)    steps = steps5;  if (frames == 7)    steps = steps6;  if (frames == 8)    steps = steps7;  if (frames == 9)    steps = steps8;  if (frames == 10)    steps = steps9;  if (frames == 11)    steps = steps10;  if (frames == 12)    steps = steps11;  if (frames == 13)    steps = steps12;        if (frames == 14)    steps = steps13;  if (frames == 15)    steps = steps14;  if (frames == 16)    steps = steps15;  if (frames == 17)    steps = steps16;  if (frames == 18)    steps = steps17;  if (frames == 19)    steps = steps18;  if (frames == 20)    steps = steps19;  if (frames == 21)    steps = steps20;  if (frames == 22)    steps = steps21;  if (frames == 23)    steps = steps22;  if (frames == 24)    steps = steps23;  if (frames == 25)    steps = steps24;  if (frames == 26)    steps = steps25;  if (frames == 27)    steps = steps26;  if (frames == 28)    steps = steps27;  if (frames == 29)    steps = steps28;  if (frames == 30)    steps = steps29;  if (frames == 31)    steps = steps30;  if (frames == 32)    steps = steps31;  if (frames == 33)    steps = steps32;  if (frames == 34)    steps = steps33;  if (frames == 35)    steps = steps34;  if (frames == 36)    steps = steps35;  if (frames == 37)    steps = steps36;  if (frames == 38)    steps = steps37;  if (frames == 39)    steps = steps38;  if (frames == 40)    steps = steps39;  // run stepper  stepper.setSpeed(motorspeed);  stepper.step(steps);   // testing  Serial.println(steps);  digitalWrite(led_pin, LOW);  // delay for next round  delay(interval_tm);  //testing       Serial.print("Time: ");  time = millis();  Serial.println(time);}// pause cycle after last cycle completevoid pause() {  digitalWrite(shutter_pin, LOW);     stepper.setSpeed(0);   stepper.step(0);}void end_session() {  digitalWrite(shutter_pin, LOW);     stepper.setSpeed(0);   stepper.step(0);  while (1) {   }}void setup() {  pinMode(pin2, INPUT); // switch input  pinMode(pin3, INPUT);  digitalWrite(pin2, HIGH); // activate pull-up resistors  digitalWrite(pin3, HIGH);  pinMode(shutter_pin, OUTPUT);  pinMode(led_pin, OUTPUT);  Serial.begin(19200);}void loop() {  // cycle exposure/dither to end of session - exits end_session  pinval2 = digitalRead(pin2); // read pin value  pinval3 = digitalRead(pin3);  if (pin2 == HIGH && pin3 == HIGH ) {    // for testing without hardware switch    //if (millis() < session_tm) {      cycle();    }    /* pause/stop - interupts exposure and completes dither cycle,      ready for next shot in sequence */    pinval2 = digitalRead(pin2); // read pin value    pinval3 = digitalRead(pin3);    while (pin2 == LOW && pin3 == HIGH) {      pause();    }    /* Note: resetting the board or turning the power off will      reset the entire session. However, the dither position will      be retained */    // stop - user end session    pinval2 = digitalRead(pin2); // read pin value    pinval3 = digitalRead(pin3);    if (pin2 == LOW && pin3 == LOW) {      end_session();    }    // end session automatically    if (frames == 40 || frames == images || millis() >= session_tm) {      end_session();         } }`

Go Up