Strona 3 z 4

: sobota 30 mar 2013, 15:22
autor: greg
Pyra, co chcesz osiągnąć w tym programie? Od tego zacznijmy.

: sobota 30 mar 2013, 15:28
autor: ElSor
Pyra pisze:Jak wspomniałem, pprzypisanie na sztywno wektora 7, kompiluje bez błędów, ale program nie działa...
w IOTN26.H mam:

Kod: Zaznacz cały

/* Timer/Counter1 Overflow */
#define TIMER1_OVF1_vect_num	5
#define TIMER1_OVF1_vect		_VECTOR(5)
#define SIG_OVERFLOW1			_VECTOR(5)

/* Timer/Counter0 Overflow */
#define TIMER0_OVF0_vect_num	6
#define TIMER0_OVF0_vect		_VECTOR(6)
#define SIG_OVERFLOW0			_VECTOR(6)

/* USI Start */
#define USI_STRT_vect_num		7
#define USI_STRT_vect			_VECTOR(7)
#define SIG_USI_START			_VECTOR(7)
Także chyba obsłużyć chcesz nie to przerwanie.

: sobota 30 mar 2013, 15:33
autor: Pyra
Witam
Jest to sterowanie zasilaczem do kolejki.
Założenie jest takie, że zmieniam kierunki i prędkość mostkiem H, tu mi wszystko gra. prędkość podąża za nastawą potencjometru. Kolejną sprawą, są przyciski "Start" i Stop" które maja powodować płynne ruszanie i zatrzymanie. Realizowałem to w ten sposób, że generowałem przerwanie sprawdzające co jakiś czas porównując wartość PWM z nastawą. Oczywiście zmiana nastawy prędkości podczas jazdy jest możliwa potencjometrem, ale też w tempie ustalonym przez program.
Przerwanie wydawało mi się tutaj optymalnym wyjściem.

Kod: Zaznacz cały

//ATTiny 26 regulator napięcia PWM z mostkiem H do kolejki
// PA0-ADC0 nastawa - potencjometr
// PA1-ADC1 pomiar prądu
// PA4 START  rozruch
// PA5 STOP  zatrzymanie
// PA6 do przodu
// PA7 do tyłu
// PB1 PWM przód
// PB3 przód
// PB2 PWM tył
// PB3 tył
// PB4 przeciążenie
// PB5 prędkość OK







#include <avr/io.h>
//#include <util/delay.h>
#include <avr/interrupt.h>

unsigned int short nastawnik;
unsigned int short jazda=0;
unsigned int short predkosc;

void przyciski&#40;&#41; //deklaracja funkcji sprawdzania przycisków
&#123;
  if &#40;&#40;&#40;PINA &_BV&#40;PA6&#41;&#41;==0&#41; && OCR1A<20&#41;
  &#123; 
  
  PORTB&=&#40;0<<PB2&#41;;
//  _delay_ms&#40;1&#41;;
  TCCR1A=0b00100011; //PWMa
  PORTB|=&#40;1<<PB0&#41;;

  &#125;
  if &#40;&#40;&#40;PINA &_BV&#40;PA7&#41;&#41;==0&#41; && OCR1A<20&#41;
  &#123;
   PORTB&=&#40;0<<PB0&#41;;
//   _delay_ms&#40;1&#41;;
   TCCR1A=0b10000011; //PWMb
   PORTB|=&#40;1<<PB2&#41;;
   &#125;

   if &#40;&#40;PINA & _BV&#40;PA4&#41;&#41;==0&#41;
   &#123;
   jazda=0;
   &#125;
   
   if &#40;&#40;PINA & _BV&#40;PA5&#41;&#41;==0&#41;
   &#123;
   jazda=1;
   &#125;
   
&#125;

void nastawa&#40;&#41; //pomiar napięcia sterującego
&#123;
  nastawnik=ADCH;
&#125;
void timer0init&#40;&#41;
&#123;
TIMSK|=_BV&#40;TOIE0&#41;;
TCCR0=0b00000101;
TCNT0=200;
&#125;

ISR&#40;TIMER0_OVF_vect&#41;
//ISR&#40;_VECTOR&#40;7&#41;&#41;
//&#123;
//  predkosc=OCR1A;
//   if &#40;&#40;jazda>0&#41; && &#40;OCR1A<nastawnik&#41;&#41;
//   &#123;
//   predkosc++;
//   &#125;

//   if &#40;&#40;jazda==0&#41; && &#40;OCR1A>20&#41;&#41;
//   &#123;
//   predkosc++;
//   &#125;
//   OCR1A=predkosc;
//   OCR1B=predkosc;
// TCNT0=200;
//&#125;

&#123;
static uint8_t LED=0b010;
LED^=0b110;
uint8_t tmp=PORTB & 0b11111001;
PORTB=&#40;tmp | LED&#41;;
&#125;



int main&#40;&#41;
&#123;
  
   TCCR1B=0b111; //konfig PWM
   OCR1C=0xFF;
   DDRB=0b00001111;
//   DDRB|=&#40;1<<PB1&#41; | &#40;1<<PB3&#41;;
   PORTA|=_BV&#40;PA6&#41; | _BV&#40;PA7&#41; | _BV&#40;PA4&#41; | _BV&#40;PA5&#41;; //podciągnięcie przycisków
   ADMUX=0b00100000;
   ADCSR=0b11100011;
 OCR1A=0x01;
 OCR1B=0x15;
  timer0init&#40;&#41;;
  sei&#40;&#41;;

for&#40;;;&#41;
&#123;
 nastawa&#40;&#41;;
 // OCR1A = nastawnik;
 //  OCR1B =nastawnik;
 //  _delay_ms&#40;50&#41;;
  przyciski&#40;&#41;; 
&#125;
Sporo linii jest zakomentażowanych, w związku z różnymi próbami...

Pozdrawiam

: sobota 30 mar 2013, 15:38
autor: greg
Proponuję skorzystać z mojego rozwiązania, czyli pracy timera w trybie CTC. Dzięki temu można ustalić w zasadzie dowolną częstotliwość przerwania, niezależnie od F_CPU. Spróbuj wrzucić mój kod w Tiny26. Ja niestety nie sprawdzę poprawności działania dla Tiny26, nie posiadam tego procesora.

: sobota 30 mar 2013, 15:47
autor: Pyra
Witam
ElSor pisze:Także chyba obsłużyć chcesz nie to przerwanie.
Opierałem się na datasheet i tam jest w tabelce na stronie 67 napisane:
"7 $006 TIMER0, OVF0 Timer/Counter0 Overflow"

greg - Sprawdzę wieczorem

Pozdrawiam

: sobota 30 mar 2013, 17:17
autor: Pyra
Witam
Porobiłem kilka prób i kompilator "nie zna" opisowych wektorów przerwań dla ATtiny26. Co bym nie wziął porównanie, przepełnienie itp. wywala ostrzeżenie.
Na razie to mi "C" przypomina zastaw do samodzielnego montażu, w którym brakuje części, a ponadto, trzeba sobie samemu zaprojektować urządzenie. ;)

Pozdrawiam

: sobota 30 mar 2013, 18:03
autor: ElSor
Nie wiem jak działa stary AVR Studio ale może podmiana toolchaina na najnowszy rozwiąże problemy :?:

: sobota 30 mar 2013, 19:11
autor: Pyra
Witam
Zainstalowałem AVR Studio 5.1, pomijam mulenie kompa przez tego molocha...
Nadal nic, kompiluje się bezbłędnie, a procek nie chce mrugać....
Czyli "w teorii, nie ma różnicy między teorią i praktyką, w praktyce jest"

W tym wypadku zostanę przy Bascomie... :roll:

Aha, program bez przerwań, działa tak jak trzeba... pomijając oczywiście to do czego miały służyć przerwania.

Pozdrawiam

: sobota 30 mar 2013, 23:51
autor: Pyra
Witam
Po nieskończonej ilości prób i poprawek... program po raz kolejny przekopiowany, zaczął działać pod AS 5.1, "nagle" też AS 4.19, zaczął rozpoznawać nazwę przerwania od przepełnienia Timer0...

Kod: Zaznacz cały

#include <avr/io.h>
#include <avr/interrupt.h>

void timer_init&#40;&#41;
&#123;
 
    TCCR0 |= &#40;1<<CS02&#41; | &#40;1<<CS00&#41;;
	TIMSK = &#40;1<<TOIE0&#41;; // Timer/Counter1 Output Compare Interrupt Enable
      DDRB = &#40;1<<PB1&#41;;
&#125;

ISR&#40;TIMER0_OVF0_vect&#41;
&#123;
    PORTB ^= &#40;1<<PB1&#41;;
&#125;

int main&#40;&#41;
&#123;
    timer_init&#40;&#41;;
    sei&#40;&#41;;
    while&#40;1&#41;;
&#125; 
Pozdrawiam

PS: Żona się na mnie obraziła i poszła spać :-(

: niedziela 31 mar 2013, 05:22
autor: ElSor
Pyra pisze:PS: Żona się na mnie obraziła i poszła spać :-(
Nic tylko się cieszyć - można spokojnie zająć się swoimi sprawami.
Pyra pisze:Po nieskończonej ilości prób i poprawek... program po raz kolejny przekopiowany, zaczął działać pod AS 5.1, "nagle" też AS 4.19, zaczął rozpoznawać nazwę przerwania od przepełnienia Timer0...
Wygląda, że winowajcą było zjedzone "0" w nazwie przerwania.
Z Twoją siłą woli, to niebawem w ATTiny13 władujesz najnowszy gregowy driver a jeszcze dołożysz kilka bajerów, żeby się pamięć nie marnowała :twisted:

: niedziela 31 mar 2013, 13:27
autor: Pyra
Witam
ElSor pisze:Wygląda, że winowajcą było zjedzone "0" w nazwie przerwania.
Też do tego doszedłem, ale... dostałem na PW program od grega i też na początku nie chciał chodzić. Potem po kilku próbach, zmianach itp, ponownie go skopiowałem i wkleiłem i zaczął działać. Był on jednak napisany na przerwanie COMPARE, zacząłem przerabiać i w końcu ruszyło też na OVF0...
Dzięki wszystkim.

Załączam działający program na ATtiny26 migający diodą na przerwaniu od przepełnienia Timer0

Kod: Zaznacz cały

#include <avr/io.h>
#include <avr/interrupt.h>

void timer_init&#40;&#41;
&#123;
 
    TCCR0 |= &#40;1<<CS02&#41; | &#40;1<<CS00&#41;; //prescaler 1024
	TIMSK = &#40;1<<TOIE0&#41;; // Timer/Counter0 przepełnienie
    DDRB = &#40;1<<PB1&#41;; //wystawienie 1 na PB1
&#125;

ISR&#40;TIMER0_OVF0_vect&#41; //program przerwania od przepełnienia Timer0
&#123;
    PORTB ^= &#40;1<<PB1&#41;; //zmiana stanu portu PB1 na przeciwny
&#125;

int main&#40;&#41;
&#123;
    timer_init&#40;&#41;;
    sei&#40;&#41;; //włączenie globalnych przerwań
    while&#40;1&#41;;
&#125; 
Pozdrawiam

: poniedziałek 01 kwie 2013, 18:55
autor: Pyra
Witam
W zasadzie program ukończony. Działa tak jak było w założeniu, pozostaje tylko dopracowanie parametrów już w układzie docelowym ...
Po skompilowaniu zajmuje 502B podczas gdy Bascomowy zajął 962B, tym nie mniej każdy język ma swoje plusy i minusy. ;)
Dzięki za pomoc. Ale dyskusji nie musimy kończyć, bo nadal się uczę, i na pewno nie tylko ja.

Pozdrawiam

: poniedziałek 01 kwie 2013, 19:44
autor: ElSor
Sławku gratuluję tak szybkiego przeniesienia programu z B na C. Widzę, że też muszę się wziąć za siebie i dokończyć kilka swoich projektów. Od ostatniej próby polubienia się z C minęło trochę czasu i przyswoiłem trochę nowej wiedzy, więc myślę, że też mi się uda szybko (w zasadzie zostało mi ADC, timer i wybudzanie z trybu uśpienia).

: poniedziałek 01 kwie 2013, 20:54
autor: Pyra
Witam
ElSor pisze:(w zasadzie zostało mi ADC, timer i wybudzanie z trybu uśpienia).
Właśnie z ADC trochę powalczyłem. Z trybu ciągłej konwersji przeszedłem na pojedynczą, bo musiałem przełączać kanały, a po takiej operacji pierwszy pomiar jest przekłamany bo zmiana kanału dokonuje się podczas konwersji i otrzymujemy poprzedni wynik. Jeśli chodzi o pojedyncze wyzwalanie, doczytałem że czas konwersji może trwać do 270cykli. Przy próbach, uzyskałem stabilne pomiary po umieszczeniu zwłoki 300&#181;s od ustawienia bitu ADSC. Nie starałem się tu za bardzo przyspieszać programu, poprzednia wartość, która była niewłaściwa to było 200&#181;s.
Co do przeniesienia z B na C, to niestety nie jest "dosłowne" ale główne założenia i niektóre rozwiązania są analogiczne.

Powoli przyswajam sobie zawiłości operacji bitowych, ustawianie, kasowanie... Zaczynam też coraz częściej stosować funkcje, zamiast wstawek w programie głównym.

Pozdrawiam

: poniedziałek 01 kwie 2013, 21:31
autor: barney
Dodawanie zwłoki po rozpoczęciu pomiaru ADCkiem ? Koniec pomiaru jest sygnalizowany zmianą bitu ADSC z 1 na 0. Aby zaczekać na koniec pomiaru wystarczy dać pętelkę:
while(ADCSRA & (1<<ADSC));
I nie trzeba kombinować z opóźnieniami, itp. Do zakończenia pomiaru pętla będzie się wykonywać cały czas i nie dopuści do wykonania kodu za nią (czyli pobrania wartości napięcia, itd).

// Wartości rejestrów są dla ATTiny13.