Kanał - ATNEL tech-forum
Wszystkie działy
Najnowsze wątki



Teraz jest 26 gru 2024, o 13:33


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 6 ] 
Autor Wiadomość
PostNapisane: 2 maja 2024, o 21:45 
Offline
Nowy

Dołączył(a): 02 maja 2024
Posty: 5
Pomógł: 0

Cześć wszystkim,

Piszę kod do mojego urządzenia do pomiaru odległości przy pomocy ultradźwięków, napotkałem jednak problem, gdyż podczas wykonywania się poniższego kodu nie otrzymuję wypisu na ekranie w Serial Monitorze. Kod jest napisany pod MCU Atmega328P zawarty w Arduino UNO. Korzystam z ArduinoIDE.
Sygnał 40 kHz jest generowany na pinie PB2, z kolei odbierany jest na pinie PB5. Zamysł jest taki, że gdy zmienna time1 będzie większa od 16 to ma być załączona obsługa przerwania PCINT5, w funkcji jego obsługi ma być podstawiona wartość time1 do zmiennej time_wait. Po wykonaniu tego podstawienia ma być wyłączone przerwanie PCINT5, wstawione 0 do zmiennej time1 tak żeby kolejny pomiar zacząć od 0 i ustawione pozwolenie perm_on = 0. Pozwolenie umieściłem po to, aby kolejny pomiar zaczął się dopiero po wypisaniu poprzedniego na ekranie.

Proszę o pomoc, naprowadzenie co robię źle.
Dzięki :)

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 3 maja 2024, o 15:12 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 26 sty 2016
Posty: 1164
Lokalizacja: Kraków
Pomógł: 93

Ech, jak używasz arduino ide, to pisz jak w arduino ide.
To, co przed while(1) wrzuć do setup(), a loop to już jest pętla nieskończona.

Podziel problem na mniejsze części. Jesteś pewien, że działają przerwania?
PCINT0 masz na PB0, nie na PB5.
Nie mam czasu, żeby dokładniej analizować kod. Co używasz do mierzenia odległości? Dobrze podłączyłeś?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 3 maja 2024, o 20:32 
Offline
Nowy

Dołączył(a): 02 maja 2024
Posty: 5
Pomógł: 0

Zmodyfikowałem kod tak że teraz przerwanie PCINT5 jest już konfigurowane w setup i nie jest ono później wyłączane po prostu wewnątrz ISR(PCINT0_vect) jest warunek if ((time1 > 82) && perm_on) który pozwala na wyłapanie tylko pierwszej zmiany na pinie PB5 i zapisaniu czasu który upłynął od nadania sygnału w zmiennej time_wait. 8-)


Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Temat do zamknięcia.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 4 maja 2024, o 22:03 
Offline
Nowy

Dołączył(a): 02 maja 2024
Posty: 5
Pomógł: 0

A jednak coś się wykrzaczyło :oops:

Wynik pomiaru ma być przedstawiony na wyświetlaczu LCD 2x16 z którym komunikacja przebiega po magistrali I2C.
Jeśli skorzystam z Serial Monitora żeby wyświetlić wyniki to działa to bez problemu i otrzymuję wyniki na w ArduinoIDE w Serial Monitorze.
Jeśli jednak chcę wykorzystać wyświetlacz LCD to wyświetla się na nim tylko:
"Czas: 8750.00"
"Odleglosc: 301.0"
Nic się wogóle nie zmienia na wyświetlaczu. Wyświetlacz jest sprawdzony odpalałem na nim inny program, żeby go sprawdzić i wszystko było okej.
Przy próbie zmiany pierwszego wypisu:
lcd.print("Czas:");
na
lcd.print("Time:");
Nic się nie zmienia na ekranie.
Poniżej kod programu:
// jest to gotowy program ultradzwiekowego miernika odleglosci
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);
volatile uint16_t time1 = 0;
volatile uint16_t time_wait = 0;
volatile uint8_t perm_on = 0;
double czas_us = 0;
double odleglosc = 0;
// ISR informujący o niepoprawnej nazwie wektora
ISR(BADISR_vect)
{
time1 = 25;
}
// ISR sterujący generowaniem paczki w odpowiednich momentach
ISR(TIMER1_COMPA_vect)
{
time1++;
if (time1 == 52000) //48000 kolejna paczka po 600 ms ( w tym czasie trzeba się wyrobić z wypisaniem na ekranie)
{
// Po osiągnięciu 48000 razy wartości TOP przez timer zmień stan bitu podłączającego/odłączającego OC1B na przeciwny
TCCR1A |= (1 << COM1B0);
// wyzeruj zmienną timer1
time1 = 0;
}
if (time1 == 8 ) // 4 * 25us = 100 us ( time1 * 25 / 2 = czas paczki impulsów)
{
// Po osiągnięciu 12 razy wartości TOP przez timer zmień stan bitu podłączającego/odłączającego OC1B na przeciwny
TCCR1A &= ~(1 << COM1B0);
}
}
ISR(PCINT0_vect) {
if ((time1 > 82) && perm_on) // jeśli odbiornik na początku łapie jakieś zakłócenie można zwiększyć time1 > x, odbędzie się to jednak kosztem minimalnej zmierzone odległości
{
time_wait = time1;
perm_on = 0;
}
}
void setup() {
_delay_ms(500);
// Rozpoczęcie transmisji szeregowej
Serial.begin(9600);
// Ustawienie PB2 jako wyjście
DDRB |= (1 << PB2);
// Ustawienie PB5 jako wejście
DDRB &= ~(0 << PB5);
// Wyczyszczenie poprzedniej zawartości rejestrów
PCICR = 0;
PCMSK0 = 0;
// Załączenie przerwań dla PCINT7..0
PCICR |= (1 << PCIE0);
// Załączenie przerwania na pinie PB5 (PCINT5)
PCMSK0 |= (1 << PCINT5);
// Wyczyszczenie poprzedniej zawartości rejestrów
TCCR1B = 0;
TCCR1A = 0;
// Tryb CTC
TCCR1A |= (1 << COM1B0);
// Prescaler: CS11 --> 8, CS10 + CS11 --> 64, CS12 --> 256
TCCR1B |= (1 << WGM12) | (1 << CS11);
// Wartość TOP
OCR1A = 24;
TIMSK1 |= (1 << OCIE1A);
perm_on = 1;
// Globalne włączenie obsługi przerwań
sei();
}
void loop() {
_delay_ms(350);
lcd.clear();
czas_us = (double)time_wait * 25 / 2;
odleglosc = 0.0344 * czas_us; // Odleglosc w centymetrach
Serial.println("Czas: ");
Serial.println(czas_us , 4); // Wypisanie czasu w mikrosekundach (4 cyfry po przecinku)
Serial.println("Odleglosc: ");
Serial.println(odleglosc , 2); // Wypisanie odleglosci w centymetrach (2 cyfry po przecinku)
lcd.setCursor(0,0);
lcd.print("Czas:");
lcd.setCursor(6,0);
lcd.print(czas_us, 4);
lcd.setCursor(0,1);
lcd.print("Odleglosc:");
lcd.setCursor(11,1);
lcd.print(odleglosc, 2);
perm_on = 1;
return(0);
}
Co może być przyczyną takiego zachowania programu? Gdzie szukać przyczyny? Proszę o pomoc w tym temacie.

------------------------ [ Dodano po: 5 minutach ]

Czy byłoby możliwe, że przerwanie ISR(TIMER1_COMPA_vect) lub ISR(PCINT0_vect) przychodzi tak szybko, że dane nie zdążą być przesłane do wyświetlacza?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 5 maja 2024, o 10:46 
Offline
Nowy

Dołączył(a): 02 maja 2024
Posty: 5
Pomógł: 0

Używam biblioteki LiquidCrystal_I2C.h w wersji 1.1.2 do obsługi wyświetlacza po I2C:
htps://github.com/johnrickman/LiquidCrystal_I2C
Jako nowy użytkownik nie mogę wstawiać linków, powyżej trzeba zmienić htps na https.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 5 maja 2024, o 11:53 
Offline
Nowy

Dołączył(a): 02 maja 2024
Posty: 5
Pomógł: 0

Brakowało mi lcd.init() w setup(). Teraz działa.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
Wyświetl posty nie starsze niż:  Sortuj wg  
Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 6 ] 

Strefa czasowa: UTC + 1


Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 2 gości


Nie możesz rozpoczynać nowych wątków
Nie możesz odpowiadać w wątkach
Nie możesz edytować swoich postów
Nie możesz usuwać swoich postów
Nie możesz dodawać załączników

Szukaj:
Skocz do:  
Sitemap
Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
phpBB SEO