Skocz do zawartości
daniel89

Robocik jeżdżący - kręci się w koło - brak reakcji na czujnik

Pomocna odpowiedź

Nie znam się na Arduino, ale tam chyba nie ustawia się rejestrów sądząc po tym co widzę tutaj:

http://sprae.jogger.pl/2011/10/14/wielozadaniowosc-w-arduino/

Rozdział: Programowanie zdarzeniowe i Biblioteka Timers.

Musisz zdecydować się czy piszesz w czystym C (wymagana zmiana bootloadera) czy w języku C dla Arduino bo teraz może to nie działać pomimo dobrego programu z racji tego, że kompilator/procek nie wie o co nam chodzi np. z ISR czy sei();

W przypadku czystego C (bardziej przyszłościowe) polecam zakupienie jakiejś książki na ten temat np. "Mikrokontrolery AVR Język C - podstawy programowania" w przypadku Arduino nie umiem doradzić.

Udostępnij ten post


Link to post
Share on other sites

http://arduino.cc/en/Reference/Interrupts

http://www.instructables.com/id/Arduino-Timer-Interrupts/

Sądząc po tej drugiej stronie Interrupts(); - tym się powinno załączać te timery , tylko z tego co Ty mi pokazałeś wynika że gościu używa mills() które dają wielozadaniowość , albo wprowadza własną bibliotekę z timerami tylko to dziwne jakieś bo przecież timery trzeba dla każdego procka i jego częstotliwości ustwić samemu , czy by miał tam wszystkie możliwe poustawiane wątpię? Powinno dać się te sprzętowe ustwić na tej stronce od arduino.cc jest referencja ustawień mógł byś na to rzucić okiem ?

Tutaj gościu w wersji polskiej ustawiał timery i używał sei(), ISR -->> http://majsterkowo.pl/zegar-cyfrowy-led-z-bajerami-czesc-iii-przerwania-zegarowe/

To jak da się to ustawić z tym sei, ISR czy nie? a co do książki to dziękuję za radę, a jakie środowisko pracy dla niego byś mi polecił AVR Studio czy Eclipse ?

Udostępnij ten post


Link to post
Share on other sites

1,2. To na pewno da się ustawić, ale dobrze by było poczekać aż wypowie się ktoś kto cokolwiek robił na arduino, posiada zestaw z arduino aby sprawdzić czy działa.

3. Eclipse

Wrzuć ten program do procka bez zmienian, dioda powinna zmieniać stan co 500 ms.

Zmień wartość zmiennej dioda_pin na numer pinu do którego masz podłączoną jakąś diodę led.

 #include <Servo.h>
   #include <interrupts.h>

   volatile boolean x=0;
volatile int dioda_pin = 1; // zmien tutaj na numer pinu do którego masz podłączoną jakas diode led

   void setup () {

       TCCR1A |= (1<<WGM12); //tryb CTC
       TCCR1B |= (1<<CS12) | (1<<CS10);  //prescaler 1024
       TIMSK1 |= (1<<OCIE1B);
       OCR1B = 7811; //500 ms

     pinMode(dioda_pin, OUTPUT);
     sei();
   };

   ISR(TIMER1_COMPB_vect){
   digitalWrite(dioda_pin, 0);
   }

   void loop () {
digitalWrite(dioda_pin, 1);
 }

lub

    #include <Servo.h>
   #include <interrupts.h>

   volatile boolean x=0;
volatile int dioda_pin = 1; // zmien tutaj na numer pinu do którego masz podłączoną jakas diode led

   void setup () {

       TCCR1A |= (1<<WGM12); //tryb CTC
       TCCR1B |= (1<<CS12) | (1<<CS10);  //prescaler 1024
       TIMSK1 |= (1<<OCIE1B);
       OCR1B = 7811; //500 ms

     pinMode(dioda_pin, OUTPUT);     
   };

   ISR(TIMER1_COMPB_vect){
   digitalWrite(dioda_pin, 0);
   }

   void loop () {
sei();
digitalWrite(dioda_pin, 1);
 }

Nie wiem czy w Arduino też tak jest, ale może masz w Fusach włączony CKDIV8 i dlatego z 1 sekundy robi się 5 sekund, albo masz źle ustawiony zegar, może jest coś takiego jak jakieś ustawienia projektu w arduino w którym trzeba ustawić jakieś taktowanie (F_CPU)

Ewentualnie, jak dioda będzie świecić albo będzie cały czas zgaszona to spróbuj wpisać do OCR1B = 1952; //1 sekunda przy 2 Mhz lub OCR1B = 7811; //1 sekunda przy 8 Mhz

Może masz coś z zegarem

Udostępnij ten post


Link to post
Share on other sites

Tutaj masz ustawienia tego leonardo (plik boards) :

leonardo.name=Arduino Leonardo
leonardo.upload.protocol=avr109
leonardo.upload.maximum_size=28672
leonardo.upload.speed=57600
leonardo.upload.disable_flushing=true
leonardo.bootloader.low_fuses=0xff
leonardo.bootloader.high_fuses=0xd8
leonardo.bootloader.extended_fuses=0xcb
leonardo.bootloader.path=caterina
leonardo.bootloader.file=Caterina-Leonardo.hex
leonardo.bootloader.unlock_bits=0x3F
leonardo.bootloader.lock_bits=0x2F
leonardo.build.mcu=atmega32u4
leonardo.build.f_cpu=16000000L
leonardo.build.vid=0x2341
leonardo.build.pid=0x8036
leonardo.build.core=arduino
leonardo.build.variant=leonardo

Po wgraniu tych dwóch Twoich przykładów dioda się zapala i pali się stale. Nawet po wyzerowaniu liczników.

Przerwania uzyskałem tylko dzięki funkcji mills(); z tego postu co mi przesłałeś - to jest tzw. wielozadaniowość, ale i tak pomimo tej funkcji powinno dać się ustawić fabryczne timery, chyba że to całe środowisko Arduino losowo wybiera timera, który wolny funkcją mills(); ale to po co by wrzucali w necie te przykłady z własnymi ustawieniami wewnętrznych timerów i podobno im działały.

Tutaj masz po angielsku obsługę timerów w Arduino taki tutorial -->> http://www.instructables.com/id/Arduino-Timer-Interrupts/?ALLSTEPS

Po modyfikacji tym programem załączam timera ale miga co 3 sekundy a powinien co 1 według Twojego wzoru. Próbowałem ustawiać na różne taktowanie na 1 MHz, na 2, na 8 i ciągle było to samo czyli miga co 3 sec na 3 sec. Oto ten kod:

 #include <Servo.h>
   #include <interrupts.h>

   volatile boolean x=0;
   volatile int dioda_pin = 1; 

   void setup () {


      TCCR1A = 0;
      TCCR1B = 0;
      TCNT1 = 0;

       OCR1B = 15624; // 1 Hz przy 16Mhz (zegar) 
       TCCR1A |= (1<<WGM12); //tryb CTC
       TCCR1B |= (1<<CS12) | (1<<CS10);  //prescaler 1024
       TIMSK1 |= (1<<OCIE1B);
       sei();

     pinMode(dioda_pin, OUTPUT);     
   };

  ISR(TIMER1_COMPB_vect){
   x=!x;
   digitalWrite(1,x) ;
   }
  void loop () {}

PS. Działa tylko po wyzerowaniu liczników.

Procek ten ma timer0, timer1, timer3 oraz timer4 (z noty katalogowej).

Udostępnij ten post


Link to post
Share on other sites

Już chyba rozgryzłem dlaczego z 1 sekundy robiły się 3 - błędny wzór. Jak kod działa to go nie ruszaj, potem resztę stopniowo dodasz jak uzyskamy miganie takie jak chcemy.

Ma być:

OCR = (F_CPU/2*PRESKALER/CZESTOTLIWOSC) -1 

7811 = (16000000/2048/2)-1

1 sekunda świeci i 1 sekunda zgaszona - 2Hz

a nie

IRQ = (F_CPU/PRESKALER/CZESTOTLIWOSC) -1

to jest wzór tj. na czestotliwość wejściową (pin ICP (Input Capture Register))

Udostępnij ten post


Link to post
Share on other sites

Próbowałem to na tych millsach zrobić , ale jak pilotem załączam to servo się po jednym impulsie obraca, a silniki ani odczyt z czujnika nie działają . Czego to jest wina ? Przecież kod powinien być dobry, oto on :

#include <IRremote.h>
#define irPin 11
IRrecv irrecv(irPin);
decode_results results;

#include <Servo.h>
# define SERVO_PIN 12
Servo servo;
byte stan = 0;
byte angle = 0;

unsigned long servo_time = millis() + 20;
unsigned long silnik_time = millis() + 500;
unsigned long pilot_time = millis() + 500;
#define trig 2
#define echo 3
int pwmMotorA=6;
int InMotorA1=5;
int InMotorA2=4;
int pwmMotorB=10;
int InMotorB1=9;
int InMotorB2=8;
int pwm = 0;


void setup() {

   irrecv.enableIRIn();

   servo.attach(SERVO_PIN);

   pinMode(pwmMotorA, OUTPUT);
 pinMode(pwmMotorB, OUTPUT);
 pinMode(InMotorA1, OUTPUT);
 pinMode(InMotorA2, OUTPUT);   
 pinMode(InMotorB1, OUTPUT);
 pinMode(InMotorB2, OUTPUT);   
 pinMode (trig, OUTPUT);
 pinMode (echo, INPUT);

}

void loop() {

unsigned long time = millis();
if (time >= pilot_time){
  if (irrecv.decode(&results)) {
  switch (results.value) {
    case 0x1D00B946:   
      stan=!stan;
      break;
    }
  irrecv.resume();
  pilot_time = time + 500;
}
}
int duration, distance;
 digitalWrite( trig, LOW);
 delayMicroseconds (2);
 digitalWrite (trig, HIGH);
 delayMicroseconds(10);
 digitalWrite (trig, LOW);
 duration = pulseIn(echo, HIGH);
 distance = (duration/2) / 29.1;

 if (time >=silnik_time && distance<=30 && stan==1) {
   unsigned long silnik_time = millis() + 500;
   digitalWrite(InMotorA1, LOW);
 digitalWrite(InMotorA2, HIGH);
 digitalWrite(InMotorB1, LOW);
 digitalWrite(InMotorB2, LOW);
 analogWrite(pwmMotorA,200);
 analogWrite(pwmMotorB,0);
  silnik_time = time + 500;
  }


 if (time >= servo_time && stan==1 && distance<15 && distance >2) {
 servo.write(angle);
 angle++;
 if (angle > 180) angle = 0;
 servo_time = time + 20;
 }
 if (time >= silnik_time && stan==1 && distance<15 && distance >2 )
 {
 unsigned long silnik_time = millis() + 500;
 digitalWrite(InMotorA1, LOW);
 digitalWrite(InMotorA2, HIGH);
 digitalWrite(InMotorB1, LOW);
 digitalWrite(InMotorB2, HIGH);
if (pwm<250) { pwm=pwm+50;}

 analogWrite(pwmMotorA, pwm);
 analogWrite(pwmMotorB, pwm);
 silnik_time = time + 500;


 }
 if(stan==0){
     analogWrite(pwmMotorB,0);
      analogWrite(pwmMotorA,0);
      servo.write(angle=90);


 }

 else if (time >=silnik_time && stan==1) {
    unsigned long silnik_time = millis() + 500;
   analogWrite(pwmMotorA,200);
 analogWrite(pwmMotorB,200);
 digitalWrite(InMotorA1, LOW);
 digitalWrite(InMotorA2, HIGH);
 digitalWrite(InMotorB1, LOW);
 digitalWrite(InMotorB2, HIGH);
 silnik_time = time + 500;}

}

Timery w tym kodzie pomimo ich modyfikacji według Twojego drugiego wzoru działają ciągle tak samo czyli co 3 sekundy się załącza i wyłącza. Gdy usunąłem zerowanie TCCR1A = 0; wtedy zaczęło migać jak oszalałe co 0,1 s. Zmieniłem wartość OCR1B i dalej było to samo . Żadna liczba którą wpisałem do kodu w OCR1B nic nie zmieniała.

Udostępnij ten post


Link to post
Share on other sites

Z tymi wewnętrznymi timerami sobie nie mogę poradzić, gdyż po ustawieniu danej wartości i tak mi przerwanie działa tylko co 3 sekundy , ale za to udało mi się napisać ten program na milsach , zdefiniowanych jako timery Arduino IDE. także już ten robocik jeździ mniej więcej tak jak chciałem. Do pełni szczęścia muszę jeszcze rozgryźć ustawienia tych timerów także jakby ktoś miał jakiś pomysł to proszę pisać śmiało .

Udostępnij ten post


Link to post
Share on other sites

Czemu w tym kodzie jak ustawię wielozadaniowość na odległość mniejszą od 10, to program wykonuje i obrót serwem i jedzie do tyłu, a jak ustawię na odległość większą od 30, aby się serwo obracało wraz z jechaniem do przodu, to serwo nie idzie tzn. wykonuje takie impulsy w bok i się cofa na 90stopni.?

#include <IRremote.h>
   #define irPin 10
   IRrecv irrecv(irPin);
   decode_results results;

   #include <Servo.h>
   # define SERVO_PIN 12
   Servo servo;
   byte stan = 0;
   byte angle = 0;

   unsigned long servo_time = millis() + 20;
   unsigned long silnik_time = millis() + 500;
 //  unsigned long pilot_time = millis() + 200;


   #define trig 2
   #define echo 3
   int pwmMotorA=5;
   int InMotorA1=7;
   int InMotorA2=4;
   int pwmMotorB=11;
   int InMotorB1=9;
   int InMotorB2=8;
   int pwm;



    void setup() {

       irrecv.enableIRIn();

     servo.attach(SERVO_PIN);

       pinMode(pwmMotorA, OUTPUT);
     pinMode(pwmMotorB, OUTPUT);
     pinMode(InMotorA1, OUTPUT);
     pinMode(InMotorA2, OUTPUT);   
     pinMode(InMotorB1, OUTPUT);
     pinMode(InMotorB2, OUTPUT);   
     pinMode (trig, OUTPUT);
     pinMode (echo, INPUT);

   }

   void loop() {

   unsigned long time = millis();
 //  if (time >= pilot_time){
      if (irrecv.decode(&results)) {
      switch (results.value) {
        case 0x1D00B946:   
          stan=!stan;
          break;
        }
      irrecv.resume();
    //  pilot_time = time + 200;
    }

   int duration, distance;
     digitalWrite( trig, LOW);
     delayMicroseconds (2);
     digitalWrite (trig, HIGH);
     delayMicroseconds(10);
     digitalWrite (trig, LOW);
     duration = pulseIn(echo, HIGH);
     distance = (duration/2) / 29.1;

    if (time >=silnik_time && distance<=30 && distance>10 && stan==1) {
       servo.write(angle=90);



            analogWrite(pwmMotorA, 225);
            digitalWrite(pwmMotorB, LOW);

       digitalWrite(InMotorA1, LOW);
     digitalWrite(InMotorA2, HIGH);
    digitalWrite(InMotorB1, LOW);
     digitalWrite(InMotorB2, LOW);
      silnik_time = time + 500;
      }


     if (time >= servo_time && stan==1 && distance<=10 ) {
    servo.write(angle);
     angle+=1;
     if (angle > 180) angle = 0;
     servo_time = time + 20;
     }
     if (time >= silnik_time && stan==1 && distance<=10 )
     {



      for  (pwm=0; pwm <=225 ; pwm=pwm+5){

            analogWrite(pwmMotorA, pwm);
            analogWrite(pwmMotorB, pwm);

            digitalWrite(InMotorA1, HIGH);
     digitalWrite(InMotorA2, LOW);
     digitalWrite(InMotorB1, HIGH);
     digitalWrite(InMotorB2, LOW);}
     silnik_time = time + 500; }





     if( stan==0){
         digitalWrite(pwmMotorB,LOW);
          digitalWrite(pwmMotorA,LOW);
         servo.write(angle=90);


     }

     if (distance > 30 && time >=silnik_time && stan==1) {
       servo.write(angle=90);


      digitalWrite(pwmMotorA,1);
    digitalWrite(pwmMotorB,1);
    digitalWrite(InMotorA1, LOW);
     digitalWrite(InMotorA2, HIGH);
     digitalWrite(InMotorB1, LOW);
     digitalWrite(InMotorB2, HIGH);
    silnik_time = time + 500;}

   }

Udostępnij ten post


Link to post
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »

×