Pierwsze oficjalne spotkanie Fi-BOT

7 października o godzinie 14:15 po zajęciach odbyło się pierwsze oficjalne spotkanie koła Fi-BOT na terenie Wydziału Fizyki. Do naszej skromnej grupy dołączyły 4 nowe osoby, dzięki którym, miejmy nadzieję, będziemy w stanie wykonać więcej projektów opartych na Arduino. Pierwsze zajęcia stanowiły rutynowe zapoznanie się z płytką Arduino Uno, jej elementami składowymi oraz formą programowania. W celu zrozumienia, jak funkcjonuje rdzeń naszej pracy, zostały zaprogramowane w prosty sposób LEDy.

W międzyczasie Panowie Przemek i Bartek kontynuowali pracę nad swoimi projektami. Informacje odnośnie projektu Pana Bartka odnaleźć można na dedykowanej stronie.

(c) J.Ch. 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.

Kontroler do pojazdu — tekstowy protokół

Pojazd sterowany – nRF24L01

Pan Przemek dalej kombinuje z komunikacją radiową na bazie układu nRF24. Jako nową zabawkę dostał JoyShield-a do Arduino, o takiego:

Jest to bardzo ciekawy układ, bo nie dość, że ma joystick oraz 7 przycisków (4 duże, kolorowe, jeden w joysticku, oraz 2 małe – mikrostyki), to ma jeszcze adaptery na radiówkę nRF24 (i inne też, ale tego nie tykamy). Wszystko złożone w „kanapkę” może pełnić funkcję kontrolera – po przyczepieniu bateryjki 9V (np. gumką recepturką).

Tekstowy protokół — kodowanie

Bazujemy na protokole tekstowym – shield odczytuje położenie joysticka, oraz 5 przycisków (chwilowo nie obsługujemy wszystkich). Dane wysyłane są przez nRF24 jako tekst, a poszczególne pola oddzielone są średnikiem. Jedna paczka danych wygląda więc tak:

507;512;0;1;1;0;0;

gdzie pierwsza liczba określa położenie joy-a na osi X, druga na osi Y, a kolejne zera i jedynki to stan logiczny 5-ciu przycisków. Bardzo proste w utworzeniu tego napisu — dzięki klasie String i jego licznie przeciążonych konstruktorach, oraz operatorowi „dodawania”.

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
 
RF24 radio(9, 10);//CE, CS
 
uint8_t rxAddr[6] = "grzyb";
 
void setup(){
  Serial.begin(9600);
  Serial.print("nRF24 INIT=");

  bool ok=radio.begin();
  Serial.println(ok);
  radio.setRetries(15, 15);

  radio.openWritingPipe(rxAddr);  
  radio.stopListening();

  //dla modulu JoyShield
  pinMode(2, INPUT);
  pinMode(3, INPUT);  
  pinMode(4, INPUT);  
  pinMode(5, INPUT);  
  pinMode(6, INPUT); 
}
 
char bufor[32];
String napis;
 
void loop(){
  //tworzymy napis wedlug naszego protokolu 
  napis = String(analogRead(A0)) + ";" + String(analogRead(A1)) + ";" + String(digitalRead(2)) + ";" + String(digitalRead(3)) + ";" + String(digitalRead(4)) + ";" + String(digitalRead(5)) + ";"  + String(digitalRead(6)) + ";";

  //przygotowujemy bufor -- tablice z napisem...
  napis.toCharArray(bufor, 32);

  //wazne! wysylamy bufor a nie napis!
  radio.write(&bufor, sizeof(bufor));
}

Ponieważ radio wysyła dane w postaci tablicy, nie możemy wysyłać obiektu napis. Dlatego korzystamy z metody toCharArray() klasy String i przekopiowujemy zawartość napisu do bufora – tablicy. W „eter” wysyłamy tablicę bufor.

Tekstowy protokół — odczyt

No właśnie, prostota użycia napisów pociąga za sobą „problem” odczytywania takich danych. W grę wchodzą bardzo przydatne metody klasy String:

  • indexOf(napis) — zwracająca pozycję napisu w danym stringu (u nas napis to średnik, którym oddzielaliśmy liczby)
  • length() — zwracająca długość stringu
  • remove(od, do) — ucinająca napis od pozycji od do pozycji do
  • substring(od, do) — zwracająca podciąg w danym napisie, od pozycji od do pozycji do
  • toInt(napis) — zamienia napis na liczbę całkowitą (int)

Poniżej program dekodujący nasz protokół – czyli zamieniający napis na

int x,y;
byte b1,b2,b3,b4,b5;

Napis wczytany z klawiatury, przez komunikację szeregową – dzięki temu możemy testować nasz program na różne sposoby (o przeniesieniu tego kodu na radio — będzie za tydzień).

void setup() {
  //dane wprowadzamy z klawiatury przez Serial
  Serial.begin(9600);
}

String tekst;
String ciag;
char znak = ';';//separator pola
int x,y; //wspolrzedne x,y
byte b1,b2,b3,b4,b5;//stan 5 przyciskow
int k,l;//pomocnicze

unsigned long int t1,t2;

void loop() {
 if(Serial.available()>0){
    tekst=Serial.readString();
    Serial.println(tekst);

    t1=micros();
    k=tekst.indexOf(znak);
    ciag=tekst.substring(0,k);
    x=ciag.toInt();
    l=k+1;
    
    k=tekst.indexOf(znak,l);
    ciag=tekst.substring(l,k);
    y=ciag.toInt();  
    l=k+1;
    
    k=tekst.indexOf(znak,l);
    ciag=tekst.substring(l,k);
    b1=ciag.toInt();
    l=k+1;

    k=tekst.indexOf(znak,l);
    ciag=tekst.substring(l,k);
    b2=ciag.toInt();  
    l=k+1;

    k=tekst.indexOf(znak,l);
    ciag=tekst.substring(l,k);
    b3=ciag.toInt();  
    l=k+1;

    k=tekst.indexOf(znak,l);
    ciag=tekst.substring(l,k);
    b4=ciag.toInt();  
    l=k+1;

    k=tekst.indexOf(znak,l);
    ciag=tekst.substring(l,k);
    b5=ciag.toInt();  
    l=k+1;
    
    t2=micros();
    
    Serial.print("Pozycja X: ");
    Serial.println(x);
    Serial.print("Pozycja Y: ");
    Serial.println(y);
    Serial.print("PRZYCISK 1: ");
    Serial.println(b1);
    Serial.print("PRZYCISK 2: ");
    Serial.println(b2);
    Serial.print("PRZYCISK 3: ");
    Serial.println(b3);
    Serial.print("PRZYCISK 4: ");
    Serial.println(b4);
    Serial.print("PRZYCISK 5: ");
    Serial.println(b5);
    Serial.print("czas dekodowaia [mikrosekundy]= ");
    Serial.println(t2-t1);
  }//if
}//loop

Tekstowy protokół — szybkość dekodowania

Wielokrotne użycie powyższych funkcji powoduje, że odkodowanie napisu 507;512;0;1;1;0;0; i zamiana go na

int x, y;
byte b1,b2,b3,b4,b5;

zajmuje dla Arduino UNO od 260 do 550 mikrosekund (czyli ~0.5ms). A dlaczego nie jeden, równy czas? Bo w zależności od postaci dekodowanego napisu mikrokotrolerek musi więcej lub mniej pracować. Mniej „męczy” się w przypadku ciągu 1;1;1;0;0;0;0; a więcej w przypadku 1012;1017;0;0;0;1;1; Dobra, zrozumiałe. A czy to duży czas? Dla człowieka to nic, dla elektroniki sporo… Czy to nam wystarczy – czy nie spowoduje opóźnień (tzw „lagów”) w sterowaniu pojazdem? O tym przekonamy się po zastosowaniu tego protokołu do pojazdu (za tydzień).

Tekstowy protokół: modyfikacje — suma kontrolna

Można pomyśleć o rozbudowie naszego protokołu na dodatkowe „pole”, będące sumą kontrolą. Jeden z pomysłów to wysumowanie wszystkich danych (w końcu to liczby całkowite) i zapisanie tej sumy jako ostatni, dodatkowy element. Dla naszego przypadku wyglądałoby to tak: 507;512;0;1;1;0;0;1021; Po stronie odbiornika dekodujemy napis, liczymy sumę x+y+b1+b2+b3+b4+b5 i porównujemy z ostatnią wartością – nazwijmy ją sumak. A Jeśli nie ma równości… odrzucamy (ignorujemy) paczkę danych i czekamy na kolejną.

Tekstowy protokół: modyfikacje — protokół binarny

Lepiej by było stworzyć podobny protokół ale binarny, czyli nie bawić się w zapis liczb w postaci stringów, dodatkowo oddzielać je przecinkami tylko wysyłać x,y jako integer, a przyciski b1,b2,b3,b4 i b5 jako byte (nie 5 bajtów, a jeden – wszak 1 bajt = 8 bitów, mamy więc nadam zapas). Zyskujemy na tym mniejsze porcje danych – wszystkie informacje z JoyShielda to tylko 5 bajtów, a nie 14 (najlepszy przypadek) czy nawet 20 bajtów (najgorszy przypadek). No i nie ma zabawy w dekodowanie danych z wykorzystaniem metod klasy String… Ale to może przy innej okazji 😉

(c) K.G.

Salon Maturzystów Perspektywy 2019

Brawa dla Pana Bartka – autora projektu – za kolejne zmiany w sofcie (GRAPH CREATORZE) oraz w Maszynie (nowe wydruki 3D). Wszystko ukończone na pierwszą, publiczną prezentację projektu podczas Salonu Maturzystów (Kampus UwB).


Znaleźli się też ciekawscy dziennikarze (ESKA, Akadera oraz Radio Białystok) którzy bombardowali pytaniami Pana Bartka (trochę zaskoczonego, mocno speszonego)
Prezentacja Maszyny wyszła bardzo dobrze, wydruki (jak widać powyżej) fajne! Warto podkreślić, że nic nie powstało w jeden wieczór – projekt wymagał już wielu godzin pracy (ile? to nawet trudno powiedzieć samemu Autorowi…). Efekty są widoczne – praca popłaca! Szczere brawa dla Pana Bartka!

Więcej o projekcie Maszyny na stronie projektu.

(c) K.G.

Zamykanie okna processinga z potwierdzeniem – SOLVED!

Niby prosta sprawa – okienko „zapisz rysunek” przy wychodzeniu z programu processinga. Nie chcemy utracić tworzonej grafiki (problem powstał podczas tworzenia obrazów w GRAPH CREATORZE – softwarze do obsługi Wielozadaniowej maszyny 2D/3D do zadań precyzyjnych), więc musi sie pojawić dialog o zapisie/odrzeceniu tworzonej pracy. Nie wystarczyło nadpisać funkcji exit() w processingu…

Okienka w Processingu oparte są (chyba) na tzw. JFrame’ach. Aby nimi sterować musimy się dostać do obiektu odpowiedzialnego za konkretne okno w aplikacji. Na początku trzeba utworzyć uchwyt do JFrame’a:

  import javax.swing.JFrame;
  import processing.awt.PSurfaceAWT;
  ...
  PSurfaceAWT surf = (PSurfaceAWT) getSurface();
  PSurfaceAWT.SmoothCanvas canvas = (PSurfaceAWT.SmoothCanvas) surf.getNative();
  JFrame jframe = (JFrame) canvas.getFrame(); //uchwyt
  ...

Otrzymany w ten sposób uchwyt można wykorzystać do modyfikacji działania okienka, np. ustawienie czynności przy zamykaniu okna:

jframe.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

Po dodaniu tych linijek kodu można zauważyć, że nic się nie zmieniło. Processing również rejestruje czy użytkownik próbuje zamknąć okno i wywołuje specjalną metodę to zamykania programu: exit(). 

Teraz wystarczy tą metodę nadpisać własnym kodem aby otrzymać dialog z potwierdzeniem wyłączenia programu:

void exit(){  // nadpisanie metody exit()
    int id = showConfirmDialog(
    frame,
    "Are you sure?", // tekst okienka
    "Exiting", // tytuł okna
    YES_NO_OPTION); // opcja przycisków
    if(id == 0){ //id 0 dla przycisku “Yes”
      super.exit();
    }
}

Okienko zwróci 0 dla przycisku “Yes”, 1 dla przysku “No” oraz -1 jeżeli zamkniemy okienko dialogowe wciskając “X”. Następnie można sprawdzić wartość zmiennej “id” i wywołać nienadpisaną wersję metody exit() przy użyciu super.exit() gdy “id” wynosi 1. Wówczas Processing zajmie się resztą i zamknie aplikację.

Do działania dialogów trzeba jeszcze dodać:

import static javax.swing.JOptionPane.*; (tutaj import jako klasa statyczna?)

Całość wygląda więc tak

import javax.swing.JFrame;
import processing.awt.PSurfaceAWT;
import static javax.swing.JOptionPane.*;

void setup(){
  size(900,600);
  PSurfaceAWT surf = (PSurfaceAWT) getSurface();
  PSurfaceAWT.SmoothCanvas canvas = (PSurfaceAWT.SmoothCanvas) surf.getNative();
  JFrame jframe = (JFrame) canvas.getFrame(); //uchwyt
  jframe.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
}
void draw(){
  rect(100,100, 200, 200);
}
void exit(){
  int id = showConfirmDialog(
    frame,
    "Are you sure?", // message
    "Exiting", // tytuł okna
    YES_NO_OPTION);
    println(id);
    if(id == 0){
      super.exit();
    }
}

I po problemie! Zachęcam do kopiowania tego rozwiząnia — (c) Bartosz Butler, 2019

Samochodzik sterowany – radiówka (nRF24L01) – oraz PM2D3D

Pojazd sterowany – nRF24L01

Pan Przemek zapoznał się z komunikacją radiową. Nadajnik i odbiornik działają, ale trzeba wysyłać konkretne dane (np. z joysticka) a nie losowe „śmieci”. Na razie powstał pomysł kodowania danych w sposób tekstowy — i pojawiły się problemy z obsługą takich „napisów”… Prace w toku 😉

Precyzyjna Maszyna (PM2D3D) – soft

Kolejne już prace nad softem – można zapisywać utworzone obrazy w GRAPH CREATORZE do plików – robi się wersja PRO 😉

Skoro jest zapis plików, to warto nie stracić swojej pracy przez nieumyślne zamknięcie programu – pojawi się stosowne okienko z potwierdzeniem (było przy tym trochę roboty, ale się udało).
Więcej o projekcie Maszyny na stronie projektu.

(c) K.G.

Błędy z biblioteką IRLib i czujka TSOP22xx — SOLVED!

Zauważyłem, że wykorzystywana biblioteka IRLib do obsługi pilotów na podczerwień MOŻE generować błędy – programy nawet się nie kompilują! Jeśli zobaczysz komunikaty o błędach w stylu:


to jest to problem z biblioteką IRLib i wersją Arduino AVR Boards. Działającym rozwiązaniem jest powrót do AVR Boards w wersji 1.6.21 (lub niższej), w której wszystko działa.

Wybierz menu Narzędzia -> Płytka -> Menadżer płytek i zmień ją (nie aktualizuj do najnowszej! no chyba, że problem jest już rozwiązany).

(c) K.G.

Samochodzik sterowany – podczerwień, TSOP – oraz PM2D3D

Pojazd sterowany – TSOP23xx

Pan Przemek uporał się z płynnym sterowaniem pojazdu (naprawa softu) – auto śmiga teraz całkiem gładko! Koła nie są uruchamiane i zatrzymywane na określony czas po wciśnięciu danego przycisku – brak efektu „czkawki”. Zamiast tego, auto zatrzymuje się gdy użytkownik zwolni przycisk na pilocie. Obsługiwane są też kody repetycji przycisku, w tym także tajemniczy kod ZERO – który pojawiał się na skutek jakiś problemów komunikacji pilota z czujką TSOP. Można więc się cieszyć, choć pilot płata figle i… mimo wszystko zrywa się komunikacja – wówczas auto się zatrzymuje (na chwilę, bo w końcu przycisk cały czas jest wciśnięty więc po chwili auto rusza). śmiało można to nazwać sukcesem. Niestety – testowy pojazd jest kiepski – 4 koła mają różne silniczki i jeden z nich działa zdecydowanie słabiej niż reszta, przez co auto marnie jeździ po podłodze (wykładzina = duże tarcie, trefne koło stoi w miejscu zamiast się kręcić). Będzie trzeba zmienić platformę (na zmodyfikowane serwomechanizmy – ale o tym za tydzień). Za tydzień też zastosowanie tej części kodu w komunikacji radiowej (lepszej niż na podczerwień).

Precyzyjna Maszyna (PM2D3D) – soft

Kolejne prace nad softem, wydruk wydaje się zachęcający 😉 Z poziomu GRAPH CREATORA można już tworzyć grafikę, która zostanie przeniesiona na kartkę papieru. Brawo!

Więcej o projekcie Maszyny na stronie projektu.

(c) K.G.