17-01-2021, 23:29
Cześć,
chciałem sterować silnikiem krokowym (step/dir) za pomocą enkodera. Kręcę enkoderem a silnik ma nadążać za nim. Licznik enkodera jest inkrementowany/dekrementowany w przerwaniu. Pozycja silnika jest zadawana z przerwania timera 0. No i udało mi się gdy kręcę enkoderem silnik nadąża za nim nawet jak obracam nim bardzo szybko (timer sterowania silnikiem plse/dir ustawiony na 10kHz).
Problem pojawia się jak pozycję silnika zadaję ze zmiennej - przy częstotliwości 10kHz silnik gubi około 90% kroków. Jak zmniejszę częstotliwość timera do 5kHz to program działa jak trzeba - ale silnik obraca się za wolno.
Nie rozumiem dlaczego tak się dzieje. Właściwie w kodzie nic nie zmieniam tylko zamiast patrzeć na zmienną enkodera EncoderPos patrzę na inną zmienną StepperPosDem.
Nie chcę korzystać z pętli głównej - w niej chcę zrobić komunikację z PC.
Korzystam z Arduino Mega 2560
Może ktoś miał już taki problem albo doświadczenie w sterowaniu krokowców (pulse/dir) z przerwania?
chciałem sterować silnikiem krokowym (step/dir) za pomocą enkodera. Kręcę enkoderem a silnik ma nadążać za nim. Licznik enkodera jest inkrementowany/dekrementowany w przerwaniu. Pozycja silnika jest zadawana z przerwania timera 0. No i udało mi się gdy kręcę enkoderem silnik nadąża za nim nawet jak obracam nim bardzo szybko (timer sterowania silnikiem plse/dir ustawiony na 10kHz).
Problem pojawia się jak pozycję silnika zadaję ze zmiennej - przy częstotliwości 10kHz silnik gubi około 90% kroków. Jak zmniejszę częstotliwość timera do 5kHz to program działa jak trzeba - ale silnik obraca się za wolno.
Nie rozumiem dlaczego tak się dzieje. Właściwie w kodzie nic nie zmieniam tylko zamiast patrzeć na zmienną enkodera EncoderPos patrzę na inną zmienną StepperPosDem.
Nie chcę korzystać z pętli głównej - w niej chcę zrobić komunikację z PC.
Korzystam z Arduino Mega 2560
Może ktoś miał już taki problem albo doświadczenie w sterowaniu krokowców (pulse/dir) z przerwania?
Kod:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <math.h>
#include "digitalWriteFast.h"
#define StepperPulse 12
#define StepperDir 13
#define EncoderPinA 2 // Encoder Pin A pin 2 and pin 3 are inturrpt pins
#define EncoderPinB 3 // Encoder Pin B
float EncoderPos = 0;
float StepperPos = 0;
float StepperPosDem = 0;
void readEncoder()
{
if(digitalRead(EncoderPinB) == digitalRead(EncoderPinA) )
{
EncoderPos = EncoderPos + 1;
}
else
{
EncoderPos = EncoderPos - 1;
}
}
void setup() {
// TIMER 0 for interrupt frequency 10000 Hz:
cli(); // stop interrupts
TCCR0A = 0; // set entire TCCR0A register to 0
TCCR0B = 0; // same for TCCR0B
TCNT0 = 0; // initialize counter value to 0
// set compare match register for 10000 Hz increments
OCR0A = 199; // = 16000000 / (8 * 10000) - 1 (must be <256)
// turn on CTC mode
TCCR0B |= (1 << WGM01);
// Set CS02, CS01 and CS00 bits for 8 prescaler
TCCR0B |= (0 << CS02) | (1 << CS01) | (0 << CS00);
// enable timer compare interrupt
TIMSK0 |= (1 << OCIE0A);
sei(); // allow interrupts
pinMode(StepperDir, OUTPUT);
pinMode(StepperPulse, OUTPUT);
pinMode(EncoderPinA, INPUT);
pinMode(EncoderPinB, INPUT);
digitalWrite(EncoderPinA, LOW);
digitalWrite(EncoderPinB, LOW);
attachInterrupt(0, readEncoder, CHANGE);
}
boolean toggle = false;
ISR(TIMER0_COMPA_vect){
/*
//OPCJA 1 - sterowanie silnikiem krokowym zmieniając zmienną StepperPosDem - nie działa
if(StepperPosDem - StepperPos > 3 || StepperPosDem - StepperPos < -3)
{
if(StepperPosDem - StepperPos < 0)
{
StepperPos = StepperPos - 4.52;
digitalWriteFast(StepperDir, 0);
}
else
{
StepperPos = StepperPos + 4.52;
digitalWriteFast(StepperDir, 1);
}
toggle = !toggle;
if(toggle)
{
digitalWriteFast(StepperPulse, HIGH);
}
else
{
digitalWriteFast(StepperPulse, LOW);
}
}*/
//OPCJA 2 - sterowanie silnikiem krokowym nadążając za EncoderPos
//zmienianą w przerwaniu enkodera - działa
if(EncoderPos - StepperPos > 3 || EncoderPos - StepperPos < -3)
{
if(EncoderPos - StepperPos < 0)
{
StepperPos = StepperPos - 4.52;
digitalWriteFast(StepperDir, 0);
}
else
{
StepperPos = StepperPos + 4.52;
digitalWriteFast(StepperDir, 1);
}
toggle = !toggle;
if(toggle)
{
digitalWriteFast(StepperPulse, HIGH);
}
else
{
digitalWriteFast(StepperPulse, LOW);
}
}
}
void loop() {
StepperPosDem = 1000; //Gdy używam OPCJI 1 w przerwaniu ISR(TIMER0_COMPA_vect) - silnik gubi kroki
}