Program only runs sporadically

I wrote the following program:

#include "SwitecX25.h"

//315 degrees of range = 315x3 steps = 945 steps
// declare motor1 with 945 steps on pins 4-7
SwitecX25 motor1(945, 5,6,7,8); //594 steps = 198 deg * 3 steps 110mph range (100mph = 180 deg)
unsigned int odo = 0; //counts for odometer
unsigned long current = 0; //current time count
unsigned long last = 0; //last time count


#define odo_speed 7 //timing for odo pulses in ms



void setup(void) {
  // run motor against stops to re-zero
  motor1.zero();   // this is a slow, blocking operation
  
  pinMode(2, INPUT_PULLUP); //enable interupt pin as input with pullup
  attachInterrupt(0, speedo, FALLING);//enable interupt input 0 on falling edge

  
  odo = 2200;
  
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
  
  digitalWrite(9, LOW);
  digitalWrite(10, LOW);
  digitalWrite(11, LOW);
  digitalWrite(12, LOW);
  
  last = micros();  //read time
}

void loop(void) {
  if (odo > 22) { //every 22 pulses corresponds to 1 rev required of odo motor
  //4606.5966 pulses per mile, 840 pulses per rev 4 of which make one motor cycle
    digitalWrite(9, HIGH);
    delay(odo_speed);
    digitalWrite(9, LOW);

    digitalWrite(10, HIGH);
    delay(odo_speed);
    digitalWrite(10, LOW);

    digitalWrite(11, HIGH);
    delay(odo_speed);
    digitalWrite(11, LOW);

    digitalWrite(12, HIGH);
    delay(odo_speed);
    digitalWrite(12, LOW);
    
    //odo = odo-22 ;
  }
}

void speedo(){
  current = micros(); //store current time
    
  motor1.setPosition(map(current - last, 809498, 736, 0, 567)); //calculate new needle position the difference between 
  //the current time stamp and the last one ic calculated and scaled for the needle
  motor1.updateBlocking();  //position needle
  //motor1.update(); //move needle by one step if applicable
  last = current; //current time is now last time
  odo++; //increment odo counter
}
[code]

only sometimes i get my pulses on outputs 9-12, any reason why ? seems to work on the uno board but not on a breadboard

[/code]

seems that using a reset button to reset the chip gets it going so seems like a power up problem

The odo variable is shared between the interrupt context and the main context, so it needs to be declared volatile. Since it's bigger than a byte, you should disable interrupts around accesses to it within the main context.

You have code to increment odo but not decrement it. The code in loop() suggests you expect it to get decremented or reset to zero periodically.

I don't know what motor1.updateBlocking() does, but if it's a blocking function as its name suggests then you shouldn't be calling that within an interrupt context. You could probably get the effect you're after by having the interrupt write (current - last) to a volatile variable (representing pulse length, I assume) and have your loop function map that to a stepper position and move the stepper accordingly.

The odo=2200 will be removed, it's there just for testing.

the idea is that a pulse from a position sensor on a wheel will trigger the interupt and update odo to say that a pulse occured. so far I'm hoping that I also have time to change the position of a speedo motor although yes maybe I should move that to the main program. For every 22 pulses the odo motor that is a 4 pole stepper needs to do one turn so once the odo variable gets over 22 the loop can run and 22 is taken off. The odo is a motor that is running a mileage counter. The whole thing is to run 2 motors on a motorbike speedo, the speed needle and the mile counter. So was the code causing a problem ? bearing in mind that I had problems before i was triggering the interrupt.

sparkylabs:
So was the code causing a problem?

Could easily have done. I suggest you fix the issues I pointed out and then see what problems you're left with. It would also be a good idea to run a simple blink sketch to make sure the Arduino keeps running and isn't getting reset, in case you have any electrical/noise issues.

I've put a 10uF capacitor on the reset pin with a 10K pullup and it seems to work fine now, the ultimate test is will it work with the high speed pulses from the motorbike wheel (5 per revolution).

I'll do as you suggest with the interrupt and take the motor code out of the interrupt and put it in the main loop, I have about 80% dead time anyway so I can take some of that up. However there should be time to calculate and update values in the interrupt routine.

sparkylabs:
I've put a 10uF capacitor on the reset pin with a 10K pullup and it seems to work fine now, the ultimate test is will it work with the high speed pulses from the motorbike wheel (5 per revolution).

Five pulses per revolution is a ridiculously slow source of input for a microprocessor, there is no reason whatsoever to use interrupts for this and it only makes matters unnecessarily complicated. A significant problem is that you are using the "delay()" function. Your "dead time" is not "80%", more like 98.8%!

Oh but there is plenty of reason, I'm timing the pulses to get the speed of the wheel, so even if I'm in the middle of an odometer pulse it will take a time reading and not miss any. At 100mph I'll be getting pulses every 5ms, If I'm spending 2mS pulsing a motor and the wheel sensor sends a pulse I'll miss it and be totally screwing up the speed indication.

The question of whether you will miss pulses when using polling (rather than interrupts) dpends on how long it takes loop() to go through 1 iteration.

With pulses at 5msec intervals there is time for something like 80,000 processor instructions so it seems to me that careful design of the program should easily fit within that.

If you do want to use interrupts then I suggest you simplify the ISR so it just records the latest version of micros() and increments a count of the number of pulses.

You can then figure out changes in the speed and any need to respond to that outside the ISR. I doubt very much if it is necessary to correct the speed every 5 msecs.

...R

Yes I'm going to take the control of the speedo motor out of the ISR as now that I have so much dead time in the rest of the program there is plenty of time, after all the speed of the wheel cannot change much from 1/5 or a turn to the next

I have the program up and running and it's all fitted to the bike. We are getting very random behaviour from the speedo which I think is due to it trying to step too fast. I managed to change the delay for the zeroing pulses and that works it seems and I've altered the acceleration table. Now the needle moves nice and smoothly but it still won't run my dummy program which is to step up one step at a time and then 0 and ten step up again.

I'm not making much sense of the library file, does anyone know how to modify it to make it more stable ? basically i need to slow down all stepping pre-sets to make sure the motor moves correctly.

Robin2:
The question of whether you will miss pulses when using polling (rather than interrupts) depends on how long it takes loop() to go through 1 iteration.

With pulses at 5msec intervals there is time for something like 80,000 processor instructions so it seems to me that careful design of the program should easily fit within that.

Oh well, we tried!

at the moment I am just trying to run the motor, something is wrong. I have a dummy program that it just supposed to zero the motor, nothing else. Instead I get random positioning of the needle and it runs both directions when I'm trying to zero it only.

sparkylabs:
at the moment I am just trying to run the motor, something is wrong. I have a dummy program that it just supposed to zero the motor, nothing else. Instead I get random positioning of the needle and it runs both directions when I'm trying to zero it only.

I'm not familiar with that driver library. Does it come with wiring diagrams and example sketches demonstrating how it's supposed to be used? Until you can make your stepper step in the required direction then it's a waste of time trying anything more complicated.

Well the motor zeroing is supposed to run it backwards against it's stop and that is all, but instead it runs both ways. I ended up writing my own sequence to get it to zero which worked fine. Conclusion is that I'll have to write my own library for the motor, will be crude, but will work

How about posting the latest version of your code?

...R

#include "SwitecX25.h"
SwitecX25 motor1(500, 5,6,7,8);





void setup() {
  // put your setup code here, to run once:
  //motor1.zero();

 }

void loop() {
  

    

}

I presume something has gone wrong with Reply #16 ????

...R

nope, that is it, that should zero the motor, instead we had it erratically roaming around the scale

Ok, then it seems that the SwitecX25 Library has magic code inside it that I know nothing about. Can you post a link to the Library's documentation.

And I do think there is a problem in your code - the line

 //motor1.zero();

probably should not be commented out.

...R