komunikacja I2C (LCD na hd44780)

(Wpis ten jest reaktywacją wpisu z 2017 r. Okazało się, że warto podzielić oryginalny wpis na dwie mniejsze części – jedna dotycząca komunikacji I2C właśnie, druga SPI).

Komunikacja I2C

To bardzo popularny interface komunikacyjny, obsługujący za pomocą tylko 2 linii aż 127 urządzeń! tymi pinami są SDA (w Arduino pin A4) oraz SDC (w Arduino pin A5). Oznacza to, że gdy podłączamy coś na I2C „tracimy” piny A4 i A5. Trudno – coś za coś. Zresztą, to nic nowego – podobnie jest z komunikacją UART – Serial.begin(xxx) – „zabiera” nam cyfrowe piny #o (TX) i #1 (RX). Przy czym UART to tylko komunikacja z jednym urządzeniem – a tutaj 2 piny i możliwość obsługi do 127 urządzeń!

HD44780 i LCD 16×2

Jako przykład komunikacji I2C użyliśmy wyświetlacza LCD 16×2 z dodatkowym sterownikiem hd44780. Po co ten sterownik? wszak to bardzo popularny wyświetlacz i można go podłączyć w ten sposób:

Przypatrzmy się uważnie co my tu widzimy – zwracam uwagę na liczbę pinów potrzebnych do obsługi wyświetlacza przez Arduino. Uważne oko uczestnika sdanaszych spotkań zauważy, że potrzeba aż 6 cyfrowych pinów. To sporo! Wszystko jest OK, gdy robimy proste programy, poznajemy moduły (w tym właśnie taki LCD) więc tych 6 pinów nie robi problemu. Ale my mamy już nasz pojazd i wykorzystanych 6 pinów do jego sterowania (a w planach kolejne rozbudowy). Jak więc poradzić sobie z problemem (powoli) kończących się pinów w Arduino UNO? Zakupić Megasa? A może użyć właśnie sterownika na I2C – wówczas potrzeba jedynie 2 pinów!

My skorzystaliśmy z wymienimego sterownika PLUS biblioteki LiquidCrystal_I2C autorstwa Franka de Brabander-a. Sporo jest podobnych bibliotek, więc doinstalowywując ją sobie warto zwrócić uwagę na tą użytą przeze mnie, a nie inną. Na szybko poznaliśmy kilka metod nowego obiektu do obsługi wyświetlacza:

include <Wire.h>   // standardowa biblioteka Arduino
#include <LiquidCrystal_I2C.h> // dolaczenie pobranej biblioteki I2C dla LCD

LiquidCrystal_I2C lcd(0x27, 16, 2);
//LiquidCrystal_I2C lcd(0x3f, 16, 2);


void setup(){
  lcd.init();
  lcd.begin(16,2);   // Inicjalizacja LCD 2x16
  
  lcd.backlight(); // zalaczenie podwietlenia 
  lcd.setCursor(0,0); // Ustawienie kursora w pozycji 0,0 (pierwszy wiersz, pierwsza kolumna)
  lcd.print("pomidor!");
  delay(500);
  lcd.setCursor(0,1); //Ustawienie kursora w pozycji 0,0 (drugi wiersz, pierwsza kolumna)
  lcd.print("LCD 16x2 I2C -- hd44780");

}

int nico=7;
void loop() 
{
   lcd.backlight(); // zalaczenie podswietlenia
   lcd.setCursor(10,1);
   lcd.print(millis()/1000);
   delay(1000);
   lcd.noBacklight(); // wylaczenie podswietlenia
   lcd.setCursor(0,0);
   lcd.print(nico);
   nico=nico*2;
   delay(1000);
}

Warto ją poznać dokładniej, czytając dokumentację.

Adresacja użądzeń I2C 

Skoro do tych samych pinów SDA i SDC można podłączyć do 127 urządzeń, to skąd wiadomo, kto co nadaje? Np. jeśli chcemy użyć dwóch LCD-ków, na jedynym wyświetlać pewne informacje a na innym inne to jak kierować napisy na różne urządzenia?

Ważne jest poznanie adresu naszego użądzenia – w tym celu należy wygooglać świetny programik i2c_scanner i wgrać do Arduino z podłączonym wyświetlaczem (zresztą, nie tylko wyświetlaczem – czymkolwiek na I2C).

A jak zmienić adres w omawianym sterowniku hd44780? Bo gdy kupiny sobie dwa takie i chcemy je wykorzystać razem to będzie to niemożliwe – oba będą mieć fabrycznie te same adresy (albo 0x27 – gdy to moduł PCF8574/PCF8574T lub 0x3f – dla modułów PCF8574A). Jest możliwość zmiany adresu zwierając ze sobą (lutując) piny A012 na spodzie modułu:

Kliknij obrazek by dowiedzieć się co i jak.

(c) K.G. 2017, 2019

 

Maskotka – reaktywacja (2-gi etap)

Pan Przemek (na moją prośbę) zabrał się za Maskotkę i wymienił w niej sterowanie: zamiast modułu Bluetooth wstawił radiówkę nRF24. Trudność polegała na zrozumieniu tego, co już zostało zrobione na płycie głównej Maskotki, co jak jest tam sterowane, co wyłączyć i co gdzie podłączyć… Udało się – moduł podłączony poprawnie, sprawdzony w działaniu z tekstowym protokołem.

Warte zapamiętania: ponieważ większości pinów na pierwszym Arduino UNO została już wykorzystana, zaszła konieczność podłączenia modułu nRF24 w dość niestandardowy sposób – pin CS radiówki został połączony z A0 Arduino. To spora rozrzutność, ale cóż zrobić, gdy nie ma już wolnych pinów cyfrowych w Arduino? Został „poświęcony” analogowy, który może działać jako cyfrowy input i właśnie działa! Potrzeba matką wynalazców 😛

W kolejnym tygodniu wymiana kół i komunikacja pomiędzy dwoma Arduino UNO w Maskotce.

(c) K.G. 2019

Ws2812b oraz potencjometr

Kolejne spotkanie z kolorowymi paskami LEDów WS2812B – tym razem sterowane potencjometrem.

UWAGA: TinkerCAD (czyli „wirtualne Arduino”) został wzbogacony właśnie o omawiane moduły RGB. Trzeba przyznać, że działają całkiem fajnie — dlatego zachęcam do zabawy nawet dla osób, które nie mają ich w realu!

Zadanie do wykonania

Zaświecić LEDem o numerze zgodnym z ustawioną wartością na potencjometrze. Inne LEDy mają być wyłączone. Kręcimy potencjometrem – „przesuwamy” LEDa. Kolor LEDa? Twój ulubiony 😉

Pozycję potencjometru odczytujemy przez funkcję analogRead(A0) – o ile środkowy pin potencjometru został podłączony do pinu A0 właśnie. W potencjometrze podłączone są także piny do GND i 5V w Arduino – zgodnie z powyższym rysunkiem.

Numer LEDa – dzielenie całkowite!

analogRead(a) zwraca wartość z przedziału 0..1023, natomiast my mamy tylko (aż?) 16 LEDów. Należy więc przeliczyć wartość a analogRead() na numer pinu… w prosty sposób:

nr = analogRead(A0)*16/1024;    //dobrze!

Ważna jest tutaj kolejność obliczeń, bo gdy napiszemy

nr = 16/1024*analogRead(A0);   //źle :-(

to choć z matematycznego punktu widzenia oba wyrażenia są równoważne, to jednak w drugim przypadku najpierw wykonuje się dzielenie – a jest tutaj dzielenie całkowite (bo zarówno 16 jak i 1024 są liczbami całkowitymi) więc wynosi zero. A zero mnożone przez cokolwiek da zawsze zero. Pierwszy wzorek jest poprawny, bo najpierw wykonamy mnożenie analogRead(A0)*16 a dopiero potem wynik tego iloczynu dzielimy (dzielenie całkowite, ale teraz nie przeszkadza) – i otrzymujemy liczbę z przedziału 0..15.

Dyskoteka – czyli efekt stroboskopu

Skoro mamy już ustalony numer LEDa, to teraz możemy zgasić wszystkie inne, a potem zaświecić tego konkretnego – o numerze nr właśnie. Ale ale… za chwilkę ponownie ustalimy położenie potencjometru, ponownie wyliczmy nr LEDa i co – ponownie zgasimy wszystkie, aby włączyć ten o numerze nr? Obawiam się, że w związku z wyłączaniem i włączaniem otrzymamy efekt „dyskoteka” (stroboskopu). Poza tym to nieprofesjonalne 😛

#include <Adafruit_NeoPixel.h>
     
#define PIN 7 
#define NDIOD 16 
int delta=1024/NDIOD;

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NDIOD, PIN, NEO_GRB + NEO_KHZ800);

int nr,poprzedni;

void setup() {
    Serial.begin(9600);
    pixels.begin(); 

    nr=analogRead(A0)/delta;
    pixels.setPixelColor(nr, 10, 0, 0);
    pixels.show();
    poprzedni = nr;
}

void loop() {
    nr=analogRead(A0)/delta;
//    Serial.println(nr); 
        
    if(nr != poprzedni){
      //AKCJA!
      Serial.print("zmiana! nr="); 
      Serial.println(nr); 
      pixels.setPixelColor(poprzedni, 0, 0, 0);
      poprzedni = nr;
      pixels.setPixelColor(nr, 10, 0, 0);
      pixels.show();
    }
}

Powyższy kod rozwiązuje efekt stroboskopu – dzięki dodatkowej zmiennej poprzedni zapamiętujemy, który LED był ostatnio włączony. W głównej pętli programu ustalamy numer LEDa zgodnego z ustawieniami potencjometru, ale „akcja” dzieje się tylko wówczas, gdy zmieniliśmy ustawienia potencjometra. Dobrze dodać wypisywanie na monitor szeregowy informacji tylko wóczas, gdy dzieje się „akcja” – dzięki temu mamy pewność, że napisy (a tym samym i sama „akcja”) wykonuje się jedynie w przypadku zmian ustawień potencjometru.

Uwaga #1 – int VS float

Proszę zwrócić uwagę, że zarówno zmienna nr jak i zmienna poprzedni są zadeklarowane jako int, co w zupełności wystarczy – nie ma potrzeby używać arytmetyki liczb rzeczywistych (powolnych, szczególnie na Arduino).

Uwaga #2 – być bardziej PRO 😛

Zwróć uwagę, że wywołuję funkcję pixels.show() tylko wówczas, gdy coś się zmieniło – niby po co miałbym wołać tą funkcję za każdym razem w loop()-ie, niezależnie od tego, czy coś się zmieniło czy nie? W końcu pixels.show() programuje LEDy zgodnie ze wcześniejszymi ustawieniami pixels.setPixelColor(), więc nie ma senesu wołać ją bez potrzeby.

Zadanie #2 (także tinkercad)

Zmienić kod tak, by świeciły się LEDy od pierwszego do tego konkretnego, zgodnego z ustawieniami potencjometru. Unikać efektu „dysko”.

Zadanie #3

Joystick to dwa potencjometry – można tu go wykorzystać i oprogramować tak, by ruch na osi X zmieniał numer LEDa (jak dotychczas), a ruch na osi Y zmieniał kolor – w jakiś zabawny sposób (może tęcza?). Proszę się pochwalić wynikami!

(c) K.G. 2019

Dni Otwartego Biznesu – oferta PZU

Otrzymaliśmy zaproszenie do uczestnictwa w szkoleniach dla studentów – PZU oferuje bilety PKP oraz jeden ciepły posiłek.

Dni Otwartego Biznesu trwają od 2 do 13 grudnia 2019 r. Każdy dzień poświęcony jest innemu zagadnieniu. Tematy omawiane na szkoleniach to m.in. robotyka, DevOps, sprytne utrzymanie aplikacji i wiele więcej. Obejrzyj załącznik z wszystkimi tematami warsztatów, opisami i datami.

Na zapisy na szkolenie studenci mają czas do 10 listopada 2019 r. Aplikacje zbierane są poprzez stronę https://www.pzu.pl/kariera/studenci/dni-otwartego-biznesu

Każdy ma możliwość zapisania się na wszystkie warsztaty jednak otrzyma zaproszenie tylko na jeden dzień szkoleń.

Szkolenia odbywają się w Warszawie w siedzibie Grupy PZU (około 10-15 min od dworca PKP). Organizator zapewnia każdemu uczestnikowi bilety PKP oraz ciepły posiłek w czasie warsztatów. Szkolenia odbywają się w godzinach 10-17.

Każdy z uczestników otrzymuje certyfikat potwierdzający zdobycie nowych kwalifikacji. Szkolenia prowadzone są przez menadżerów co najmniej średniego szczebla.

(c) K.G. 2019

Ws2812b, potencjometr oraz Monster

Kolejne spotkanie z kolorowymi paskami LEDów WS2812B zapętlonymi w koło – sterowane potencjometrem. Dla nowych studentów to fajna zabawa – odczytujemy napięcie funkcją analogRead() a efekt przekładamy na wędrujący w kole piksel… Prace trwają 😉

Do zapamiętania:

  1. elektronika/fizyka: dzielnik napięć
  2. informatyka: dzielenie całkowite i dzielenie rzeczywiste, rzutowanie typów
  3. Arduino: sprawdź wartość wyjścia 5V i dostosuj formułki do obliczania odczytanego napięcia
  4. Arduino: przetworniki ADC – rozdzielczość pomiaru, błąd odczytu.
W tinkercadzie można też sprawdzić potencjometr!

Efekty w kółku – bez delay()a

Dwie strony naszego kółka wyświetlają różne kolory – rozpoczynamy od góry kółka, gdzie kolejne piksele zapalają się co zadany interwał czasu, a po „dotarciu” do środka kółka – piksele wracają (gaszą się). Ale… lewa strona jest cztery razy szybsza niż prawa strona. Na dodatek nie można używać funkcji delay()!

D E M O

Brawo dla Pana Łukasza!

Monster – moduł sterownika silnika DC

Mocny sterownik do silników DC – prąc pracy 12A (chwilowy 30A), napięcie pracy 16 V – bije na głowę poczciwego L293x i dlatego jest MONSTEREM 😉 12A to brzmi dumnie, ale w postaci BEZ RADIATORA to możemy pracować do 6A.

Układ nazywa się VNH2SP30 i jest warty polecenia, ale uwaga – w wielu sklepach (nawet tych renomowanych) można kupić uszkodzone sterowniki, które kręcą kółkami tylko w jedną stronę! Sprzedawcy wymieniają wadliwe sztuki, ale piszę to w celu zaoszczędzenia nerwów – gdy coś nie działa a powinno.

Moduł Monster dla pojedynczego silnika DC – ze stronki https://protosupplies.com/product/vnh2sp30-single-monster-motor-module/

Warto przeczytać opis użycia modułu oraz jego specyfikację, gdy coś nie idzie tak, jak powinno.

Generalnie wszystko jest proste: 5V, GND do odpowiednich na Arduino, INA oraz INB do dowlonych pinów w Arduino, którymi chcemy sterować silniczkiem (tak samo jak w L293x), ale pin PWM musi być podłączony do Arduino – w przeciwnym razie sterowanie odbywa się z ZERO procent mocy. Pin EN (enabled) może być podłączony do 5V w Arduino, choć i tak jest w stanie wysokim, więc układ jest włączony, pin CS to diagnostyczny, na razie pomijamy (odczytuje prąd pracy układu, temperaturę…). Silnik podłączamy do OUTA oraz OUTB, natomiast zasilanie do + (plus) oraz – (minus) po przeciwnej stronie modułu – uwaga na właściwą polaryzację! Tutaj ważne jest ten plus i minus, oby nie odwrotnie!

No i ostatnia ISOTONA kwestia: zasilanie musi być przynajmniej 5.5V, nie może być mniej!

(c) K.G. 2019

Ws2812b oraz millis()

Kolejne spotkanie z kolorowymi paskami LEDów WS2812B – tym razem zapętlone w koło, więc efekt fajny!

Efekty mogą być fajne, ale… programując tylko takie „kółeczka” nie martwimy się używaniem funkcji delay(). To dobrze w tym prostym przypadku. Ale czy zawsze tak można?

Zadanie do wykonania

migać pierwszym LEDem co 1 sek (włączać na 1 sek, wyłączać na 1 sek), migać drugim LEDem co 30 sek — wszystko bez użycia funkcji delay() ! Po co to nam? A chodzi o to, że efekty świetlne mają pojawiać się niezależnie od innych rzeczy dziejących się w „międzyczasie”, nie chcemy ich stopować delay()em. W naszym przypadku zamierzamy jeździć pojazdami, które sterowane będą bezprzewodowo przez moduły radiowe nRF24L więc nie chcemy zatrzymywać odbioru sterowania wyświetlając efekty na kolorowych kółkach. Jak to zrobić?

Liczniki czasu – funkcja millis()

Powiedzmy, że chcemy wykonać pewne instrukcje co interwał czasu (może być 150 ms, może być 3777 ms albo dowolnie).

unsigned long int interwal = 3777;
unsigned long int t1,t2;
unsigned long int licznik = 0;


void loop(){
  t1 = millis();
  //
  //rozne operacje, ktorych nie chcemy zatrzymywac
  //
  t2 = millis();
  licznik += (t2 - t1);

  if (licznik >= interwal){
    //wykonaj zadania co dany interwal
    licznik = 0;
  }
}//loop

Powyższy kod to szkic postępowania w celu uzyskania „wielozadaniowości” na platformie Arduino 😉 Na początku pętli loop() zapisujemy aktualny czasu do zmiennej t1, wykonujemy wszystkie potrzebne instrukcje, których nie chcemy przerywać, na koniec ponownie zapisujemy czas do zmiennej t2. Zwiększamy licznik czasu (zmienna licznik) właśnie o czas wykonania pętli loop(), czyli różnicę t2-t1. Następnie sprawdzamy czy licznik „napełnił się” do zadanego interwału – jeśli tak, wykonujemy zadania i zerujemy licznik. Oczywiście możemy mieć wiele liczników, jak też i różne interwały…

(c) K.G. 2019

Pierwsze spotkanie w nowym semestrze 2019/2020!

Nowy semestr w roku akademickim 2019/2020

Zapraszam zainteresowanych na zajęcia koła Fi-BOT w poniedziałki, o godz. 14:15 do sali 1064 (Wydział Fizyki, Kampus). Będziemy pracować nad rozpoczętymi projektami. Mile widziani studenci ze znajomością platformy Arduino, ale i tak liczy się zaangażowanie. Zapraszam!

Radiówka i „grzebek”

Pan Przemek zrealizował proste sterowanie „grzybkiem” (zamiast przycisków). Proste, bo wychylenie gałki (odczyt z analogRead() w zakresie 0..1023) powyżej ustalonej wartości (>700) oznacza ruch w jedną stronę z pełną prędkością, natomiast gałka w drugą stronę (<300) w przeciwną. Tak samo z drugą osią. W kolejnym podejściu prace nad uzależnieniem prędkości od wartości wychylenia (PWM silników skalowane analogReadem grzybka).

Jak zawsze coś się musiało rozlutować…

PM2D3D Nowe wózki i akceleracja

Pan Bartek udoskonalił nowe wózki i ciągle pracuje nad akceleracją… Więcej o projekcie PM2D3D na dedykowanej stronie.

(c) K.G.

PM2D3D – nowe wózki i akceleracja

Nowe wózki

Pan Bartek napracował się przy nowych wózkach – przemyślana konstrukcja, projekt 3D a potem wydruk. No i mamy konkretny wynik! Nie tylko wizualny, ale i jakościowy – dzięki nim maszyna jest niższa, a także pracuje stabilniej!


Uważny obserwator bloga zauważy też, że RAMA ma krótsze nóżki 😉 To też pozytywnie wpływa na wibracje pisaka.

Akceleracja ruchu

Jeszcze nie ukończona, ale prace są bardzo zaawansowane – co przedstawia poniższy film:

Więcej o projekcie PM2D3D na dedykowanej stronie.

(c) K.G.

Pojazd sterowany — działa na radio!

Pojazd sterowany – nRF24L01

Pan Przemek oprogramował pojazd – działa przez radiówkę! Na razie sterowanie odbywa się przy pomocy 4-rech przycisków, a „grzybek” nie jest jeszcze oprogramowany. Od czegoś trzeba było zacząć 😉

Chwilowo nie zgłaszamy problemów z opóźnieniami spowodowanymi tekstowym protokołem – zobaczymy, co będzie dalej. Powyżej warsztat pracy Pana Przemka – jak widać kontroler jest minimalistyczny, a temat stworzenia fajniejszego pozostawiamy na później. Prace nad pojazdem sterowanym przez radio idą w bardzo dobrym kierunku. Za tydzień upgrade Maskotki, a potem nowe podwozie (+ modyfikacje serwomechanizmów do pracy ciągłej).

PM2D3D – małe kroczki, nowe wózki

Przełączenie sterowników silników krokowych na 1/16 kroku (poprzednio: 1/8 kroku) poskutkowało cichszą pracą, lekko wolniejszą – ale za to dokładniejszą (mniej „chwiejnych” linii). Poniżej fajny wydruk:

Dodatkowo trwają prace nad kolejną zmianą konstrukcji – nowe wózki, wydrukowane w 3D, mają zastąpić te z profili Makerbeama.  Zobaczymy co wyjdzie.


Więcej o projekcie PM2D3D na dedykowanej stronie.

(c) K.G.

Arduino z taktowaniem 600MHz?

Z serwisu Forbot o płytce Teensy 4.0, kompatybilnej z Arduino UNO

Technical Specifications

  • ARM Cortex-M7 at 600 MHz
  • 1024K RAM (512K is tightly coupled)
  • 2048K Flash (64K reserved for recovery & EEPROM emulation)
  • 2 USB ports, both 480 MBit/sec
  • 3 CAN Bus (1 with CAN FD)
  • 2 I2S Digital Audio
  • 1 S/PDIF Digital Audio
  • 1 SDIO (4 bit) native SD
  • 3 SPI, all with 16 word FIFO
  • 3 I2C, all with 4 byte FIFO
  • 7 Serial, all with 4 byte FIFO
  • 32 general purpose DMA channels
  • 31 PWM pins
  • 40 digital pins, all interrrupt capable
  • 14 analog pins, 2 ADCs on chip
  • Cryptographic Acceleration
  • Random Number Generator
  • RTC for date/time
  • Programmable FlexIO
  • Pixel Processing Pipeline
  • Peripheral cross triggering
  • Power On/Off management

Test wydajności:

Cena około 100 zł i jest dostępna. Fajnie. Ale jeszcze fajniejsze jest małe zużycie prądu (jak na 600MHz) – około 0.1A, a także RTC (zegarek – ale trzeba podłączyć bateryjkę). Bardzo ciekawa płytka.

(c) K. G. 2019