logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Wprowadzanie zmian w parametrach sterujących wentylatorem za pomocą EEPROM i USART na Attiny 13

koczis_ws 09 Sty 2022 19:38 1350 39
  • #1 19810473
    koczis_ws
    Poziom 27  
    Witam serdecznie,
    Mam pewien program sterujący wentylatorem w łazience, który już działa dobrze.
    Ten program ma pewne parametry, które nim sterują. Niby mogę te parametry wpisać jako stałe do programu i w wypadku ich zmiany zaprogramować mikrokontroler ponownie. Ale ja chciałbym je wpisać do EEPROM i korygować ich wartości przez USART bez konieczności ponownego programowania.
    Attiny 13 nie ma wbudowanego USART, więc zainstalowałem programowy.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Przesyłanie danych działa dobrze, ale jest problem z tym, że procedura blokuje działanie głównej pętli programu. Nie pomogło dodanie warunku liczenia pętli (zmienna n).
    Testowy program wygląda tak:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    LED powinien migać, ale niestety zapala się na stałe a mignie tylko w trakcie przesyłania danych przez USART.
    Miganie pojawia się gdy odblokuję linię '//return -1;' w funkcji uart_rx ale wtedy nie ma transmisji.
  • #2 19810552
    GanzConrad
    Poziom 25  
    Nie pasuje mi to, że "Dana" to char, skoro przyjmuje wartości ujemne.
    Led powinien migać 10 razy na sekundę, może miga szybciej bo masz źle ustawioną stałą czasową dla _delay_ms ?
    Poza tym, miganie zrobiłbym w Timerze, który byłby wyłączany na czas działania Uart.
  • #3 19810559
    tmf
    VIP Zasłużony dla elektroda
    Przede wszystkim masz błędną koncepcję obsługi UART - przenieś to na przerwania. Tak jak masz to teraz, z delay w pętli głównej to będzie działać tylko przez przypadek i okresowo.
    Po drugie, jeśli w funkcji odbioru znaku czekasz w nieskończoność na jakiś stan to nic dziwnego, że ci to blokuje pętlę główną.
    Moja rada - podepnij rxd pod pin z przerwaniem, w ISR odbieraj znaki. Wtedy nawet od biedy z delay. Wersja optymalniejsza - użyj dodatkowo timera i jego przerwań.
    Zajrzyj też do noty Atmela na temat implementacji soft UART - masz tam gotowe kody.
  • #4 19810612
    koczis_ws
    Poziom 27  
    GanzConrad napisał:
    Nie pasuje mi to, że "Dana" to char, skoro przyjmuje wartości ujemne.

    Tak , ale tu tylko test a zmiana Dana na int nic nie zmieniła.
    GanzConrad napisał:
    Led powinien migać 10 razy na sekundę, może miga szybciej bo masz źle ustawioną stałą czasową dla _delay_ms ?

    Jak odremuję tą podaną linię to miga 10 razy na sek.
    tmf napisał:
    Tak jak masz to teraz, z delay w pętli głównej to będzie działać tylko przez przypadek i okresowo.

    Nie, działa perfekcyjnie.
    tmf napisał:
    Po drugie, jeśli w funkcji odbioru znaku czekasz w nieskończoność na jakiś stan to nic dziwnego, że ci to blokuje pętlę główną.

    Przecież dodałem inkrementację zmiennej n i po przepełnieniu powinno wyjść z pętli i funkcji (return -1; ).

    Może proponowane zmiany poprawiły by sytuację, ale narazie nie mam pewności czy wystarczy na to skąpej pamięci Tiny13.
    Ale w międzyczasie wymyśliłem inne podejście. Niech sobie funkcja blokuje, ale będzie ona wywołana po uruchomieniu guzikiem procedury ustawiania parametrów zamiast wymuszania jakimś kodem z USART. W końcu w 99.99999999% czasu pracy programu USART nie będzie potrzebny.
  • #5 19811399
    kamyczek
    Poziom 38  
    Tiny 13 nie ma sprzętowego uarta ,więc programowy uart zawsze będzie blokował wykonywanie pętli głównej programu . Jego obsługę musi wykonać mikrokontroler tak jak program. Żeby to mogło działać to trzeba użyć przerwań i timera do obsługi uarta programowego a w czasie gdy ten liczy opóźnienia obsługiwać resztę . Tyle że najlepiej to takie rzeczy pisze się w asemblerze , szczególnie jak mikrokontroler ma 1k pamięci i takie zasoby jak ten . Możesz za to użyć sobie attiny 25, 45 lub 85 tam masz w najlepszym układzie 8k ale to i tak nie zmieni faktu że obsługa uarta musi być napisana z pomocą timera i przerwań , bo o wielowątkowości .to przy 8 bitowcach możesz zapomnieć .
  • #6 19811870
    koczis_ws
    Poziom 27  
    Ja to rozumiem. Przesyłanie danych tym programowym UART działa b. dobrze. Zastanawiam się tylko czemu inkrementacja zmiennej n nie wyrywa z pętli.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Układ mam już zrobiony łącznie z PCB pod Tinny13, więc pozostanę przy tym. Jak bym miał zmieniać mikrokontroler to na Atmegę 8, która ma wbudowany UART.
    Ale poddałem się i zrobiłem tak, że wejście do funkcji przesyłania parametrów jest wyzwalane przyciskiem, a kończy się po przesłaniu bajtu STOP ( u mnie to znak @).
    Wybrany parametr ustawia się przesyłając kolejno znak START ( u mnie # ), potem numer parametru a następnie wartość. Wartości są jednobajtowe co upraszcza sprawę.
    Bajty przesyłam terminalem Putty, ale mam własny i przerobię go tak żeby ułatwić sobie pracę.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Jeśli ktoś ma lepszy spsób to chętnie zobaczę.
  • #7 19814750
    koczis_ws
    Poziom 27  
    No i wyszło szydło z wora :(
    Wziąłem inną Tiny i nie działa przesył przez UART. Podejrzewam różnice w taktowaniu zegara.
    Myślę, że można pożonglować stałą 'UART_BIT_LENGTH' tylko nie wiem jak to ugryźć.
    Próbowałem różnie, np. zapisywałem w EEPROM żeby nie przeprogramowywać co chwilę mikrokontrolera z różnymi wartościami stałej , ale głównym problemem jest to , że _delay_us(wartosc) przyjmuje tylko stałą. Czy jest jakaś możliwość definiowania stałej za pomocą zmiennej?
  • #8 19814779
    gps79
    Poziom 35  
    koczis_ws napisał:
    Podejrzewam różnice w taktowaniu zegara.
    Fusebity dobrze ustawiłeś?

    no i chyba lepiej będzie użyć F_CPU
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #10 19814824
    kamyczek
    Poziom 38  
    No trzeba tam wpisać wartość kalibracji przy starcie i będzie ok. T13 sama automatycznie tego nie robi , ale jak ktoś potrafi się pobawić to da się to zrobić tak że sama sobie odczytuje i wpisuje gdzie trzeba i działa bo pisałem swego czasu urządzenie które działa na rc i używa wewnętrznego oscylatora RC .
  • #12 19814843
    gps79
    Poziom 35  
    Przy pierwszym odbieranym bicie zaczekałbym połowę czasu trwania bitu, aby zminimalizować desynchronizację która może nastąpić w trakcie odbierania bajtu:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #13 19814865
    kamyczek
    Poziom 38  
    Wartość kalibracji masz wpisaną fabrycznie w układ , więc czytasz i wpisujesz albo w program , albo jak potrafisz ją przeczytać bezpośrednio , bo tak też się da , to czytasz to co producent wpisał i wpisujesz do odpowiedniego rejestry i masz jak dobrze pamiętam 0,1% błąd więc uart programowy działa jak powinien , chyba że ustawisz jakąś kosmicznie dużą prędkość to się jakiś byk może zdarzyć ...
  • #14 19814886
    bart-projects
    Poziom 29  
    @kamyczek - słabo znasz sprawę

    Do @koczis_ws . Układ jest wstępnie skalibrowany. Bajt kalibracji znajduje się w rejonie sygnatury i jest automatycznie wpisywany do rejestru zarządzającego oscylatorem OSCCAL. Wiec teoretycznie nie musisz tego robić.

    Można o tym poczytać w minutę. Otwierasz PDF do Tiny13 i w wyszukiwarce wpisujesz OSCCAL - kieruje do Register summary gdzie sobie przy nim klikasz na stronę (u mnie 26) i gotowe.
    Potem szukasz "SIGNATURE" i znowu kilka zdań. Prosta sprawa.

    Niemniej można go skalibrować "ręcznie" dokładniej, ale przy pomocy na przykład AVR ISP MkII w Atmel Studio. On go tam jakoś programuje i każe mu machać pinem po czym mierzy częstotliwość. Na końcu może Tobie zapisać bajt kalibracji we flash albo eeprom. Taki bajt wtedy musisz sobie odczytać sam i po restarcie uC wpisać do OSCCAL.
    Możesz też "tuningować na piechotę sam pisząc jakiś programik do częstotliwości i przed uruchomieniem programu zmieniając wartość OSCCAL.
    Zapisaną wartość bajtu kalibracji odczytuje wiekszość programatorów więc wtedy najczęściej wartość zwiększasz sobie tylko lub zmniejszasz o jeden.
    Należy pamiętać, że tuning OSCCAL jest przewidziany dla prędkości 4.8MHz i 9.6MHz a nie dla 1.2MHz

    Wprowadzanie zmian w parametrach sterujących wentylatorem za pomocą EEPROM i USART na Attiny 13
  • #15 19814906
    koczis_ws
    Poziom 27  
    bart-projects napisał:
    Należy pamiętać, że tuning OSCCAL jest przewidziany dla prędkości 4.8MHz i 9.6MHz a nie dla 1.2MHz

    I tu jest pies itd. . . . .
    Ja mam prędkość 1MHz bo przy takiej są prawidłowe czasy dla _delay. Więc zabawa z kalibracją nie wchodzi w rachubę.
    W bibliotece do wysyłania danych jest możliwość korekcji czasu poprzez ustawienie OCR0A.
    Dla odbierania trzeba by wyliczyć stałą 'UART_BIT_LENGTH', ale jak to zrobić?
  • #16 19814907
    kamyczek
    Poziom 38  
    Tak z pewnością tak napisali , tylko czasem warto to sprawdzić , bo bywa z tym ci piszą różnie . Można sobie zwrócić przez uarta wartość rejestru , będzie widać czy na pewno tak jest jak napisali .
  • #17 19814937
    jvoytech
    Poziom 21  
    koczis_ws napisał:
    bart-projects napisał:
    Należy pamiętać, że tuning OSCCAL jest przewidziany dla prędkości 4.8MHz i 9.6MHz a nie dla 1.2MHz

    I tu jest pies itd. . . . .
    Ja mam prędkość 1MHz bo przy takiej są prawidłowe czasy dla _delay. ...

    _delay jest softwarowe i żeby czasy były prawidłowe musisz zadeklarować F_CPU (jako makro lub w ustawieniach preprocesora) tak aby był zgodny z częstotliwością rezonatora oraz ewentualnie dodatkowo uwzględnić podzielniki częstotliwości (fusebity).

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Cytat:
    Dla odbierania trzeba by wyliczyć stałą 'UART_BIT_LENGTH', ale jak to zrobić?

    trzeba zamienić to 1e-6 na "1/F_CPU", żeby nie być zależny od tego 1MHz, na przykład tak:
    Kod: Objective-C
    Zaloguj się, aby zobaczyć kod
  • #18 19814947
    bart-projects
    Poziom 29  
    Przecież to na palcach albo w głowie można policzyć... :D
    Tiny13A jest specyficzne bo ma oscylator 9.6MHz a nie 8MHz jak reszta uC więc z podzielnikiem CKDIV8 kręci się na 1.2MHz.
    Teraz najprostsze... Baud 9600 tak? F_CPU 9600_000 tak? Ktoś nie widzi korelacji?
    Zostaje 1000 ... a przy podzielniku CKDIV8 125....

    Tylko o tej "specyficzności" Tiny13 trzeba pamiętać bo potem żadne "czasy" nie pasują.
  • #19 19815059
    koczis_ws
    Poziom 27  
    bart-projects napisał:
    Przecież to na palcach albo w głowie można policzyć...

    Można łatwo policzyć pod warunkiem, że oscylator daje dokładnie 9.6 MHz. Ale jak nie, to trzeba zmierzyć tą prawdziwą i dla niej wyliczyć prawidłowe UART_BIT_LENGTH.
  • #20 19817786
    kamyczek
    Poziom 38  
    Jeśli kalibracja wpisuje się automatycznie tak jak tam pisał bart to się kolego czepiasz nie tego co powinieneś . Masz błąd w programie i tylko tyle , wygeneruj sobie w prosty sposób sygnał prostokątny na wolnym pinie i zweryfikuj jaką ma częstotliwość . Uart powinien działać bez problemu przy błędzie prędkości rzędu 2% .
    I zacznij kolego od analizatora i wysłania 1 bajtu i sprawdzenia jaką ma rzeczywiście prędkość , i jak wygląda przebieg , czy przypadkiem nie jest zdeformowany przez inne operacje wykonywane losowo w czasie wysyłania przez uart .
  • #21 19818313
    koczis_ws
    Poziom 27  
    kamyczek napisał:
    Jeśli kalibracja wpisuje się automatycznie tak jak tam pisał bart to się kolego czepiasz nie tego co powinieneś . Masz błąd w programie i tylko tyle

    Zmierzyłem rzeczywiste czasy generowane przez _delay_ms dla dwóch egzemplaży Tiny, z których jeden pracował a drugi nie. Różnice czasów wynosiły 6.25%. Przeliczyłem i skorygowałem program dla tego niepracującego.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    We właściwościach projektu wpisałem F_CPU=1060000UL
    To zadziałało :) Teraz mogę ustawiać parametry przez UART.
  • #22 19819946
    koczis_ws
    Poziom 27  
    Opanowałem odbieranie danych z UART, ale pojawił sie nowy problem.
    Napisałem sobie własny terminal i przystosowałem go do przesyłania parametrów , które są zapisywane do EEPROM mikrokontrolera. Działa, ale problem jest z przesyłaniem bajtów większych niż 127. Problem jest raczej w programie w VisualBASIC a nie w AVR bo testowałem i AVR odbiera 8 bitów.
    Poniżej fragmet programu terminala odpowiedzialny za przesył danych w sekwencji: # , nr_danej , wartość_danej.
    Kod: VB.net
    Zaloguj się, aby zobaczyć kod


    Dla danych większych niż 127 zawsze zapisuje się do EEPROM wartość '3F' niezależnie od przesyłanej danej.
  • #23 19820210
    bart-projects
    Poziom 29  
    Jak to przesyłasz? Hexstring czy Binary? Jak parsujesz?
    Podstawowy typ w VB to INT ale da się własnie zadeklarować coś jako Byte i potem parse...

    Po tym co przedstawiłeś nie da sie pomóc, a;le bez problemu można w VB działać na bajtach tyllko np. 0F dla PC to F kiedy ma to wysłać.
  • #24 19820221
    kamyczek
    Poziom 38  
    koczis_ws napisał:
    Zmierzyłem rzeczywiste czasy generowane przez _delay_ms dla dwóch egzemplarzy Tiny, z których jeden pracował a drugi nie. Różnice czasów wynosiły 6.25%. Przeliczyłem i skorygowałem program dla tego niepracującego.


    To teraz sobie odpowiedz sam jak Tiny sobie automatycznie wpisuje kalibrację , ale oczywiście są tacy co wierzą ślepo w to co napisali ... Jeśli będziesz cwany to sobie zrobisz taką procedurę ,która albo będzie czytała z eeproma , albo z flash , albo bezpośrednio z zapisanej w fabryce kalibracji i przy starcie wpisze ją w odpowiedni rejestr bo z tego co dobrze pamiętam że błąd po wpisaniu kalibracji jest albo 0,1 albo 0,5% co się z twoją wartością jakoś zupełnie nie pokrywa . Jak zrobisz wszystko jak należy to każdy działa bez liczenia i myślenia ...
  • #25 19820227
    koczis_ws
    Poziom 27  
    Typy zmiennych są w listingu. Tu przesyłam jako String, próbowałem jako Byte ale to nic nie dało. Poczytałem o kodach ASCII i znalazłem informację, że kody powyżej 127 mogą być przesyłane w 2 bajtach i może o to chodzi, że przesyłany jest tylko starszy bajt ? Ja tu wysyłam paczkę 3 bajtów po jednym bajcie co 0.4 sek.

    Dodano po 14 [minuty]:

    kamyczek napisał:
    Jeśli będziesz cwany to sobie zrobisz taką procedurę ,która albo będzie czytała z eeproma , albo z flash , albo bezpośrednio z zapisanej w fabryce kalibracji i przy starcie wpisze ją w odpowiedni rejestr


    Niestety nie jestem taki cwany i sobie nie poradzę. A za takie "pomoce" serdecznie dziękuję.
  • #26 19820812
    bart-projects
    Poziom 29  
    Napisz jakich danych sie spodziewasz w urządzeniu bo myslisz ze to mu wysyłasz :D
    Kody powyżej 127 nie muszą być wysyłane w dwóch bajtach. Do 127 to zwykłe ASCII potem są okrojone narodowe i tak mozna kupić wysiwietlacze z róznym kodowaniem, ale zawsze te pierwsze127 znaków jest wspólne.
    Co innego UTF8(dwa bajty) i tu na pewno nie ma znaczenia bo ASCII to najcząściej jeden bajt.
  • #27 19820963
    koczis_ws
    Poziom 27  
    Skoro przesyłanie bajtów mniejszych od 127 odbywa się bez problemu to wymyśliłem chytry sposób.
    W programie VB dzielę parametr przez 2 , a w programie AVR mnożę przez 2 przed wpisem do EEPROM. Oczywiście ma to pewne wady. Z liczbami parzystymi jest OK ale nieparzyste po takiej konwersji są mniejsze lub większe o 1. No i jest mniejsza rozdzielczość, ale tu nie ma to znaczenia. Narazie tak zostawię bo szkoda czasu, a może w przyszłości znajdę bardziej eleganckie rozwiązanie.
  • #28 19820973
    bart-projects
    Poziom 29  
    Tu nie chodzi o chytrość. 127 można zakodować na siedmiu bitach. Tak jak osiem na trzech bitach...
    Mozna mieć typ char albo właśnie taki który tylko pomiesci 12 ale też -128
    Wzsystko zależy od implementacji i tego co przetwarza urządzenie końcowe.

    Dodano po 7 [minuty]:

    może inaczej.. signed or unsigned char
    Ta jedynka binarnie z przodu robi róznicę

Podsumowanie tematu

W dyskusji poruszono temat wprowadzania zmian w parametrach sterujących wentylatorem za pomocą EEPROM i programowego USART na mikrokontrolerze Attiny 13. Użytkownik chciał zrealizować możliwość modyfikacji parametrów bez konieczności ponownego programowania mikrokontrolera. Zwrócono uwagę na problemy z implementacją programowego UART, który blokuje główną pętlę programu. Użytkownicy sugerowali przeniesienie obsługi UART na przerwania oraz użycie timerów, aby uniknąć blokowania. Wskazano również na konieczność kalibracji częstotliwości oraz dostosowania stałych czasowych w kodzie. Użytkownik ostatecznie zaimplementował rozwiązanie, które umożliwia przesyłanie parametrów do EEPROM, jednak napotkał trudności z przesyłaniem wartości większych niż 127, co rozwiązano poprzez modyfikację przesyłanych danych.
Podsumowanie wygenerowane przez model językowy.
REKLAMA