[SOLVED] Problems in the Timer interrupt routine

tales von milet
Mon Oct 30, 2017 7:27 pm
moin moin,
ich habe da ein kleines Problem. Index wird in der handler_servos nicht 0. sie fängt scheinbar immer bei 1 an.
ich sehe da aber keinen fehler.
I have a little problem there. Index does not get 0 in handler_servos, it always starts at 1.
but I do not see any mistakes.

#define IndexMax 3 // Anzahl der servos
#define ServoMIN 500 // Minimalwert des Servos in usec
#define ServoMAX 2500 // Miaximalwert des Servos in usec
#define ServoHome 1500 // Mittelwert des Servos in usec
#define INTERVAL 20000 // 20ms

unsigned int S[]={PB5,PB6,PB7}; // Pins für die Servos;
volatile int W[IndexMax]; // Impulswerte der Servos in usec
volatile int Index=0; // Zeiger auf Servo/Daten
volatile int Index1=0;

void Servo_init(void)
{
int i;
for (i=0;i<IndexMax;i++)
{
pinMode(S[i], OUTPUT); // Pins als Ausgang definieren
W[i]=ServoHome; // vorbelegung der Servos
sprintf(fbuffer, "Pin %i ist Servo %i",S[i],i);
Serial.println(fbuffer);
}
noInterrupts(); // Alle Inte Timer2.setChannel1Mode(TIMER_OUTPUTCOMPARE);
Timer2.setPeriod(ServoHome*IndexMax); // in microseconds
Timer2.attachCompare1Interrupt(handler_servos);
Timer2.setCompare1(1); // overflow might be small
interrupts(); // alle Interrupts scharf schalten
}

void handler_servos(void)
{
int i,T1wert;
digitalWrite(S[Index1],LOW); // aktuellen Servo abschalten
if (Index < IndexMax)
{
digitalWrite(S[Index],HIGH); // anschalten
T1wert=W[Index]; // in microseconds
Index1=Index; // Servo zum abschalten merken
Index++; // nächsten vorbereiten
}
else
{
Index= 0;
T1wert=INTERVAL;
for (i=0;i<IndexMax;i++) T1wert-=W[i];
}
Timer2.setPeriod(T1wert); // in microseconds
}


stevestrong
Tue Oct 31, 2017 8:24 am
I moved the topic since it was not about PRs, bugs nor about enhancements.

You are missing the standard beginning and ending part:
Timer2.pause(); // stop the timer
... // set timer parameters
Timer2.resume(); // let the timer run


tales von milet
Wed Nov 01, 2017 11:54 am
Thanks for moving the message.
the Timer2.pause & resume does not solve the problem but unfortunately.

stevestrong
Wed Nov 01, 2017 3:09 pm
You should tell us what exactly the sketch is supposed to do.

Btw:
– you have to start the timer, otherwise the interrupt will not work or maybe work once, that is why Index will not be incremented more than once.
– you must not use the channel 1 interrupt, you could use the counter update event interrupt:
Timer2.pause();
Timer2.setPeriod(ServoHome*IndexMax); // in microseconds
Timer2.attachInterrupt(0, handler_servos); // channel 0 is the update event
Timer2.resume();


tales von milet
Wed Nov 01, 2017 4:47 pm
moin moin,

I have programmed the same process into an arduino nano. there the software runs without error. the variable index is processed from 0 to IndexMax.
but for the stm32 the variable index is only used from 1 to IndexMax.

Timer2 starts properly, but when Index == IndexMax it should be index = 0 but it is 1.
This the output STM32
https://www.dropbox.com/s/y93ga186qai31 … 6.jpg?dl=0
and this Arduino Nano
https://www.dropbox.com/s/q8f0pscddlf4e … 8.jpg?dl=0


RogerClark
Wed Nov 01, 2017 9:07 pm
Please explain what you are trying to achieve.

Reverse engineering someone elses code is very hard and time consuming, and no one has much free time nowadays, so unless you make people’s life easy they are not likely to be able to help


zoomx
Thu Nov 02, 2017 9:38 am
I understand that after
Index = 0;

tales von milet
Thu Nov 02, 2017 1:40 pm
Moin moin,
I changed the procedure so:
void handler_servos (void)
{
int i, T1 value;
Timer2.pause (); // stop the timer
digital write (S [index1], LOW); // current servo index1
if (Index <IndexMax)
{
digital write (S [Index], HIGH); // index
T1wert = W [index]; // in microseconds
Index1 = index; // note servo to index1
++ index; // prepare next
}
else
{
T1wert = INTERVAL;
for (i = 0; i <IndexMax; i ++) T1value-=W [i];
Index = 0;
}
Timer2.setPeriod (T1wert); // in microseconds
Timer2.resume (); // let the timer run
}

stevestrong
Thu Nov 02, 2017 2:13 pm
[tales von milet – Thu Nov 02, 2017 1:40 pm] –
that is not the solution.

To find out the solution we should first now what do you want to achieve.

Do you want to control servos? using a single timer?
How should the control signals look like? Like in the picture of Arduino Nano posted above? There are only 2 signals.
Do you want to control more servos? How many?
Are you limited to output the signals on the pins you declared in your software or are you free to change them?
Because there are some pins which output signals directly from timers, so no need to toggle some other pins.
Must the control signals be correlated in phase? Otherwise one could use up to 4 timers generating PWM signals with different duty cycle.

What board do you use?
Which core do you use? (How did you install the STM32 software?)
Do you use Arduino IDE?


tales von milet
Thu Nov 02, 2017 6:09 pm
moin moin,
Do you want to control servos? using a single timer? Yes
How should the control signals look like? Like in the picture of Arduino Nano posted above? There are only 2 signals. Yes
Do you want to control more servos? How many? Yes, 11 for roboterarms and legs
Are you limited to output the signals on the pins you declared in your software or are you free to change them? i can change this Pin
Because there are some pins which output signals directly from timers, so no need to toggle some other pins. i know this
Must the control signals be correlated in phase? Otherwise one could use up to 4 timers generating PWM signals with different duty cycle. i Know this

What board do you use? STM32-Maple Mini
Which core do you use? (How did you install the STM32 software?) STM32F103C8T6 Optimize alle version testet
Do you use Arduino IDE? Yes, V.1.8.4

This project run with one Nano per arms or leg. i try to port this to stm32.
but the stm32 make crazzy things.


stevestrong
Thu Nov 02, 2017 6:30 pm
Check this out.
I have tested it and it seems to work.
What you were missing was the timer refresh function.
#define IndexMax 3 // Anzahl der servos
#define ServoMIN 500 // Minimalwert des Servos in usec
#define ServoMAX 2500 // Miaximalwert des Servos in usec
#define ServoHome 1500 // Mittelwert des Servos in usec
#define INTERVAL 20000 // 20ms

unsigned int S[]={PB5,PB6,PB7}; // Pins für die Servos;
volatile int W[IndexMax]; // Impulswerte der Servos in usec
volatile int Index=0; // Zeiger auf Servo/Daten
volatile int Index1=0;
char fbuffer[256];

void Servo_init(void)
{
for (uint8_t i=0;i<IndexMax;i++)
{
pinMode(S[i], OUTPUT); // Pins als Ausgang definieren
W[i]=ServoHome; // vorbelegung der Servos
sprintf(fbuffer, "Pin %i ist Servo %i",S[i],i);
Serial.println(fbuffer);
}
Timer2.pause(); // Alle Inte Timer2.setChannel1Mode(TIMER_OUTPUTCOMPARE);
Timer2.setPeriod(ServoHome*IndexMax); // in microseconds
Timer2.attachInterrupt(0, handler_servos);
Timer2.resume(); // alle Interrupts scharf schalten
}

void handler_servos(void)
{
int i,T1wert;
digitalWrite(S[Index1],LOW); // aktuellen Servo abschalten
if (Index < IndexMax)
{
digitalWrite(S[Index],HIGH); // anschalten
T1wert=W[Index]; // in microseconds
Index1=Index; // Servo zum abschalten merken
Index++; // nächsten vorbereiten
}
else
{
Index= 0;
T1wert=INTERVAL;
for (i=0;i<IndexMax;i++) T1wert-=W[i];
}
Timer2.setPeriod(T1wert); // in microseconds
Timer2.refresh();
}

void setup() {
// put your setup code here, to run once:
Servo_init();
}

void loop() {
// put your main code here, to run repeatedly:
}


tales von milet
Thu Nov 02, 2017 6:52 pm
moin moin,
thanks, now it works
what’s the difference between Timer2.resume and Timer2.refresh?
is there a wiki for the timers?

stevestrong
Thu Nov 02, 2017 7:00 pm
Here is the official documentation: http://docs.leaflabs.com/static.leaflab … dwaretimer

Please mark the topic as [SOLVED] if it is ok now.

By the way, your variables are all “int” type which means 32 bit signed.
Are you sure this is what you want? I suggest to use the “uint8_t” or “uint16_t” where ever makes sense, just to signalize their limits.
Also, there is no need to make all variables “volatile”, because they are only used in the ISR.
The W[] array, which I think will change the values in the main loop, can also remain non-volatile.

STM32_MultiServoControl.ino
(1.98 KiB) Downloaded 145 times

Leave a Reply

Your email address will not be published. Required fields are marked *