Na początek cały kod:
Mam nadzieję że wszystkich autorów wymieniłem.
Jeśli o kimś zapomniałem- to przepraszam i proszę się zgłosić.
Teraz jest tak:
Jest impulsator podpięty na port C4 i C5.
Przez I2C sterujemy PCF8574 który wysyła na ULN odpowiednie sekwencje impulsów do sterowania silnika krokowego.
No i prawie działa.
W wersji if(bit_is_clear()) działa prawie dobrze.
Ale są drgania styków- gubi impulsy- więc dodałem debounce().
Normalnie debounce powinien sprawdzać stan co kilka ms a drgania ustają po ok.20ms.
Ale w przypadku impulsatora przy szybkim kręceniu stany się zmieniają co 2.5ms.
Tak że sprawdzam impulsator co 1ms.
Ale w tym wypadku działa tylko przy szybkim kręceniu impulsatorem a przy wolnym brak reakcji.
No i już nie wiem- zrezygnować z programowego deboucingu?
Czy może jakoś da się zrobić?
Zarówno w wersji if(bit_is_clear()) jak i w wersji z debounce() gubi co jakiś czas impulsy.
#include <stdint.h>
#include <avr/io.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#include "HD44780.h"//radzio
#include "TWI.h" //radzio
#define PCF8574ADDR 0x20//adres PCF
#define MAX_OBR 220 //to daje 0.576ms/kroczek
#define PRAWO 1
#define LEWO -1
#define STOP 0
//zmienne globalne
volatile uint8_t gflaga_pomiaru;
volatile uint8_t g_accel_decel_counter;
volatile uint8_t gflaga_impulsatora;
volatile int16_t NoOfPulses;
//prototypy funkcji
void tmf_impulsator(void);
uint8_t debounce(void);
void SetAdcKanal(void);
void twi_advance_step(int8_t nsteps);
void ster_silnika (void);
void licznik (int8_t kierunek_zliczania);
int main(void)
{
char buf_pozycja[5];
char *text="Kolejne";
char *text1="testy";
DDRB=255;
PORTB=255;
DDRC=0;
PORTC=255;
TCCR2=_BV(CS22)|_BV(CS21);//|_BV(CS20);silnik sterujemy co 4ms
TCCR0=_BV(CS01)|_BV(CS00);//impulsator sprawdzamy co 1.024ms
TIMSK=_BV(TOIE0)|_BV(TOIE2);
// ustawianie I2C
TWBR=18;
//LCD
LCD_Initalize();
LCD_WriteText(text);
LCD_GoTo(0,1);
LCD_WriteText(text1);
_delay_ms(300);
LCD_GoTo(20,1);
LCD_WriteText("Pozycja");
sei();
while(1)
{
if(gflaga_pomiaru>=200)// wyświetlacz co 200ms
{
LCD_GoTo(28,1);
LCD_WriteText(" ");
itoa(NoOfPulses,buf_pozycja,10);
LCD_GoTo(28,1);
LCD_WriteText(buf_pozycja);
gflaga_pomiaru=0;
}
if (gflaga_impulsatora)
{
tmf_impulsator();// co 1.024ms
// debounce();
gflaga_impulsatora=0;
}
}//koniec while
}//koniec main
ISR(TIMER0_OVF_vect) //co 1.024ms
{
gflaga_pomiaru++;
gflaga_impulsatora++;
}
ISR(TIMER2_OVF_vect) //co 4ms- maleje do 0.57ms dla szybkich obrotów
{
ster_silnika();
}
//Program Dr_Vee do sterowania silnika- nieco zmieniony
enum { NUM_STEPS = 8 };
enum { STEP_MASK = 0xf0 };
// Uklad I2C: A B C D x x x x
static const uint8_t steps[NUM_STEPS] =
{
0b10000000, 0b11000000, 0b01000000, 0b01100000, 0b00100000, 0b00110000, 0b00010000, 0b10010000
};
// o 1/2 kroku w prawo: advance_step(1)
// o 1/2 kroku w lewo: advance_step(-1)
void twi_advance_step(int8_t nsteps)// zmieniony przez _marek
{
if ( nsteps )
{
static uint8_t stepNum;
stepNum += nsteps;
stepNum %= NUM_STEPS;
twistart();
twiwrite(0x40 | (PCF8574ADDR << 1));
twiwrite(steps[stepNum] | 0x0f);//maska na resztę pinów
twistop();
}
}
//funkcja sterująca silnikiem by sulfur- troszkę zmieniona
void ster_silnika (void)
{
//zakladam, ze -1 - LEWO, 0 - STOP, 1 - PRAWO
//-zostało zrobione w #define
//oraz ze silnik po uruchomieniu stoi
static int8_t kierunek_silnika = STOP;
int8_t kierunek_impulsatora = STOP;
if(NoOfPulses>0)//wybrany_kierunek_obrotow==1)
{
kierunek_impulsatora = PRAWO;
}
if(NoOfPulses<0)//wybrany_kierunek_obrotow==-1)
{
kierunek_impulsatora = LEWO;
}
if(abs(NoOfPulses)==0)//ten impulsator nie jest doskonały- co jakiś czas gubi impulsy
{
kierunek_impulsatora=STOP;
}
if (kierunek_impulsatora == STOP && kierunek_silnika == STOP ) return;// nic do roboty, dowidzenia
if (kierunek_impulsatora == kierunek_silnika)
{
if (g_accel_decel_counter <= MAX_OBR)
{
if(g_accel_decel_counter<abs(NoOfPulses))// przyspieszamy- w lewo albo w prawo, i2c itd
{
g_accel_decel_counter++;
}
else
{
g_accel_decel_counter=abs(NoOfPulses);
}
TCNT2=g_accel_decel_counter;
twi_advance_step(kierunek_silnika);//to działa
}
}
else
{
if (g_accel_decel_counter > 0)
{
if(g_accel_decel_counter>abs(NoOfPulses))//zwalniamy- od prawej albo od lewej, i2c itd
{
g_accel_decel_counter--;
}
else
{
g_accel_decel_counter=abs(NoOfPulses);
}
TCNT2=g_accel_decel_counter;
twi_advance_step(kierunek_silnika);//to działa
}
else
{
kierunek_silnika = kierunek_impulsatora;
}
}
}
void tmf_impulsator(void)//funkcja by tmf
{
uint8_t i=0;
static uint8_t enc_last;
uint8_t stan_przyciskow;
stan_przyciskow=debounce();
PORTB=stan_przyciskow;
// if(bit_is_clear(PINC,4)) i++;//sprawdzenie czy impulsator się ruszył
if (stan_przyciskow==0x10) i++;
// if(bit_is_clear(PINC,5)) i^=3; // convert gray to binary- tak samo jak na bramce XOR
if (stan_przyciskow==0x20) i^=3;
i-=enc_last;
enc_last+=i;
if(i & 1)
{ // Na bicie 0 sprawdzamy czy coś się zmieniło //bit 0 = value (1)
if(i & 2)// na bicie 1 sprawdzamy kierunek//bit 1 = direction (+/-)
{
NoOfPulses++;
if (NoOfPulses>=MAX_OBR) NoOfPulses=MAX_OBR;
}
else
{
NoOfPulses--;
if (NoOfPulses<=(-MAX_OBR)) NoOfPulses=(-MAX_OBR);
}
}
}
uint8_t debounce(void)// funkcja Freddiego Chopina
{
static uint8_t last;
uint8_t port;
uint8_t wynik;
port = PINC;
wynik=port&(~last);
last=port;
return wynik;
}
Mam nadzieję że wszystkich autorów wymieniłem.
Jeśli o kimś zapomniałem- to przepraszam i proszę się zgłosić.
Teraz jest tak:
Jest impulsator podpięty na port C4 i C5.
Przez I2C sterujemy PCF8574 który wysyła na ULN odpowiednie sekwencje impulsów do sterowania silnika krokowego.
No i prawie działa.
W wersji if(bit_is_clear()) działa prawie dobrze.
Ale są drgania styków- gubi impulsy- więc dodałem debounce().
Normalnie debounce powinien sprawdzać stan co kilka ms a drgania ustają po ok.20ms.
Ale w przypadku impulsatora przy szybkim kręceniu stany się zmieniają co 2.5ms.
Tak że sprawdzam impulsator co 1ms.
Ale w tym wypadku działa tylko przy szybkim kręceniu impulsatorem a przy wolnym brak reakcji.
No i już nie wiem- zrezygnować z programowego deboucingu?
Czy może jakoś da się zrobić?
Zarówno w wersji if(bit_is_clear()) jak i w wersji z debounce() gubi co jakiś czas impulsy.