Skocz do zawartości

Linefollower - pierwsze podejście - schemat


karol93

Pomocna odpowiedź

Cześć!

Przepraszam, że tak nagle zniknąłem - nowa praca, obowiązki, plus trzeba było zarobić na zabawki 😉).

Zaopatrzyłem się już praktycznie we wszystko, co potrzeba do zbudowania linefollowera z mojego projektu.

Zacząłem od uczenia się obsługi WS2812B. Używam UARTa w trybie SPI. Zgodnie z książką Tomasza Francuza. Wszystko mi pięknie działa, prócz jednej rzeczy - wariuje mi pierwsza dioda, kolejne działają już bez problemu.

Kolorki wysyłane są w trybie GRB, po 8 bitów na kolor, od najstarszego, do najmłodszego bitu.

Problem jest taki, że wszystkie pomysły na kolorowe szlaczki itd działają, świecą na zadany kolor, jednak pierwsza dioda, która dostaje sygnał z Tx ZAWSZE świecie na zielono..... Czyli chyba jest to jakiś problem zakłóceniami ? Wrzuciłem kondensator 100uF na zasilanie diod, droga od Tx do DIN jest najkrótsza jak tylko się da, na linii danych wrzuciłem rezystor 330ohm.

Niestety, żadne zmiany nie pomagają.... Próby ustawienia innego trybu SPI, przeczytanie 5x całej noty nt. UARTA i SPI nic nie pomogły.... Zmiana diody,procesora , inne podejście do kodu - niestety, nie pomagają.

Używam Arduino ProMini, czyli z Atmega328P na 16Mhz, używam 5V z zasilacza typowo do płytek stykowych. Niestety, oscyloskopu nie mam, tak wiec nie jestem w stanie sprawdzić, jak wygląda ten sygnał.

Dlatego też zwracam się do Was z prośbą o pomoc 😉)

Może akurat ktoś z Was zauważy, w czym problem.

/*
* WS2812B_SPI.c
*
* Created: 2014-08-24 17:18:27
*  Author: tmf
*/ 

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

#define LEDNO   16           //Liczba LEDˇw

static inline void SPI_WS_Reset()   //Taktowanie SPI dla sygnału RESET
{
UBRR0=49;  //Dla 16 MHz daje to czas trwania bitu równy 6,25 us, a bajtu 50 us
}

static inline void SPI_WS_Data()   //Taktowanie SPI dla transferu danych
{
UBRR0=2;    //Dla 16 MHz daje to czas wysyłania bitu równy 375 ns
}

void WS2812B_init()
{
DDRD|=_BV(PD4);     //Pin SCK jest wyjściem - master mode
UCSR0C=_BV(UMSEL01) | _BV(UMSEL00) | _BV(UCPHA0); // | _BV(UCPOL0); //Tryb SPI
UCSR0B=_BV(TXEN0);  //Potrzebujemy tylko MOSI
}

void WS2812B_reset()
{
SPI_WS_Reset();     //Dostosuj szybkość SPI
while(!(UCSR0A & _BV(UDRE0)));  //Zaczekaj na miejsce w buforze
UCSR0A|=_BV(TXC0);  //Skasuj flagę sygnalizującą nadanie ramki
UDR0=0;             //Wyślij impuls ujemny o czasie trwania >50 us
while((UCSR0A & _BV(TXC0)) == 0);  //Zaczekaj na koniec sygnału RESET
SPI_WS_Data();      //Przełącz szybkość SPI do nadawania danych
}

void WS2812B_send(uint8_t byte)
{
void WS2812B_UDR(uint8_t byte)
{
	while(!(UCSR0A & _BV(UDRE0)));  //Zaczekaj na miejsce w buforze
	UDR0 = byte;       //Umieść w nim dane do wysłania
}

uint8_t tmp=0x00;
if(byte & 0x80) tmp=0b11100000; else tmp=0b10000000;
if(byte & 0x40) tmp|=0b00001110; else tmp|=0b00001000;
WS2812B_UDR(tmp);  //Wyślij bity 7-6
tmp=0x00;
if(byte & 0x20) tmp=0b11100000; else tmp=0b10000000;
if(byte & 0x10) tmp|=0b00001110; else tmp|=0b00001000;
WS2812B_UDR(tmp);  //Wyślij bity 5-4
tmp=0x00;
if(byte & 0x08) tmp=0b11100000; else tmp=0b10000000;
if(byte & 0x04) tmp|=0b00001110; else tmp|=0b00001000;
WS2812B_UDR(tmp);  //Wyślij bity 3-2	
tmp=0x00;
if(byte & 0x02) tmp=0b11100000; else tmp=0b10000000;
if(byte & 0x01) tmp|=0b00001110; else tmp|=0b00001000;
WS2812B_UDR(tmp);  //Wyślij bity 1-0	
}

int main(void)
{
WS2812B_init();    //Zainicjuj interfejs

   while(1)
   {

/*	WS2812B_reset();   //Mamy zresetowany interfejs i SPI dostosowane do nadawania danych

WS2812B_send(0);
WS2812B_send(0);
WS2812B_send(255);

WS2812B_send(0);
WS2812B_send(255);
WS2812B_send(0);

WS2812B_send(255);
WS2812B_send(0);
WS2812B_send(0);
*/
uint8_t cnt=LEDNO;
uint8_t offset=0;
uint8_t delta=256/LEDNO;

while(1)
{
	WS2812B_reset();
	while(cnt--)
	{
		WS2812B_send(0);
		WS2812B_send(cnt*delta+offset);
		WS2812B_send(0);
	}
	offset+=delta;
	_delay_ms(10);
}

   }
}
Link do komentarza
Share on other sites

Moim zdaniem dość ryzykowne jest przełączanie prędkości interfejsu w locie. Nie wiadomo jak dokładnie jest skonstruowany blok UARTa i kiedy wchodzi nowa prędkość. Trochę nie rozumiem po co tak to zostało zrobione. Przecież impuls resetowania strumienia danych można uzyskać bez przełączania prędkości: wystarczy wysłać wiele bajtów 00 z prędkością normalną dla wysyłania danych RGB. Moja propozycja jest taka:

1. Przesuń wywołanie funkcji SPI_WS_Data() gdzieś na początek main (ale po WS2812B_init()) - będzie wywoływana tylko raz na początku a prędkość będzie ustawiana raz na zawsze.

2. Przenieś funkcję WS2812B_UDR() na poziom wyżej tak by była dostępna dla każdego a nie tylko z wnętrza WS2812B_send().

3. Zmodyfikuj funkcję WS2812B_reset() tak, by wysyłała np. 20 bajtów 0x00 w prostej pętli "for" bez żadnych zmian prędkości np. za pomocą wielokrotnego wywołania "uwolnionej" funkcji WS2812B_UDR().

To na pewno ujednolici obsługę UARTa i być może pomoże na złe zapalanie pierwszej diody.

BTW: W DS procesora znalazłem takie zdanie: "IMPORTANT: The Baud Rate must be set after the transmitter is enabled". Tego program zmieniający prędkość w locie nie spełnia.

Co to za nowa praca?

  • Pomogłeś! 1
Link do komentarza
Share on other sites

Zaraz wprowadzę zmiany w życie 🙂.

Jako że skończyłem inżynierke z Mechaniki i Budowy Maszyn, to aktualnie uczę się projektować linie produkcyjne karoserii do samochodów 😉.

PS. Chociaż nie powiem, elektronika zdecydowanie bardziej interesująca... 🙂 Tyle, że za mało wiem, żeby móc na tym zarobić, a nie mam na tyle czasu, żeby nadgonić wszystkich którzy zajmują się tym już np. od technikum 😉.

EDIT: DZIAŁA ! 🙂

Zrobiłem wszystko według zaleceń i elegancko zaczęło działać 🙂 Dzięki za pomoc 🙂

Zdecydowałem się na takie rozwiązanie, z racji że powinno bardzo mocno ograniczyć wykorzystanie procesora przy całym projekcie. Inne biblioteki wykorzystują coś co nazywają bit-banging (jeśli dobrze pamiętam), a wtedy procesor cały czas jest obciążony wystawianiem jedynek i zer na linii. Tutaj wgrywam sobie do rejestru i mogę co innego robić.

Nie będzie problemów z przerwaniami itd, jeśli chciałbym np. wrzucić enkoder na koła, albo cokolwiek innego.

Link do komentarza
Share on other sites

O, fajnie że działa.

Niestety nie będzie tak dobrze. Zauważ, że transmisja przez UART/SPI jest ekstremalnie szybka. Wysłanie całego bajtu zajmuje 3us a nie możesz niczego wstrzymać dopóki wszystkiego nie wyślesz bo złamiesz timing transmisji. Nie masz szans obsłużyć jakiegokolwiek przerwania między bajtami i de facto cała pętla wysyłania wszystkich diodek powinna być ujęta w nawiasy sekcji krytycznej cli()/sei(). Jedyny czas wolny to impuls resetujący - może być dowolnej długości i nie zmienia stanu LEDów więc tylko wtedy możesz coś zrobić. Możesz do problemu podejść inaczej: wywoływać pętlę wysyłania na żądanie, tylko wtedy gdy zmieniasz zawartość łańcucha. Tak czy siak nie może w systemie być zdarzeń/przerwań na tyle pilnych lub częstych, by nie mogły poczekać na zakończenie całej transmisji do diodek 🙁 Przemyśl to.

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.