niedziela, 3 grudnia 2017

Funkcje programu sterującego - opisanie rzeczy.

Całość programu sterującego rozpoczyna się od zaimportowania biblioteki - właściwie jednej z najpopularniejszych bibliotek pod platformę BeagleBone Black - mianowicie Adafruit-BBIO. Sposób instalacji tej biblioteki na platformie opisano dokładnie TUTAJ. Niemniej, żeby nie było Wam tak łatwo - sami sobie znajdźcie obraz Debiana na którym to działa :) W każdym bądź razie jak już to Zrobicie...
Było co innego, ale będzie czerstwo i nudno gdyż zostałem zaszczuty czymś o "obowiązkach domowych" - typical... :-D
No dość już ględzenia o nieczym!!!

Można za pomocą instrukcji opisanej w powyższym linku ustawiać i kontrolować zachowanie portów naszego Beagle'a.

Z innej beczki. Inna sprawa, że w Kanadzie można mieć Rysia domowego (normalnie ruchy jak kot - bo to jest kot :/):


A w Polsce...
Za to takie szczenię dobrze ułożone będzie na długooooo Waszym best frendem.

Aby program mógł w pełni funkcjonować potrzebne jest zdefiniowanie kilku stałych sterujących poszczególnymi fazami "wykonywania się" programu. Oto one:

PIN_SPEED_CH1_RightOkreśla, że ​​pin 14, portu rozszerzeń (P9) steruje prędkością prawego koła przedniego;

PIN_SPEED_CH2_LeftOkreśla, że ​​pin 16, portu rozszerzeń (P9) steruje prędkością lewego koła przedniego;

PIN_SPEED_CH3_RightOkreśla, że ​​pin 19 portu rozszerzeń (P8) steruje prędkością prawego koła tylnego;

PIN_SPEED_CH4_LeftOkreśla, że ​​pin 13 portu rozszerzeń (P8) steruje prędkością lewego koła tylnego.

PIN_DIR_CH1_LEFT:  Określa, że pin 27 portu rozszerzeń (P9) steruje kierunkiem obrotu prawego koła przedniego;

PIN_DIR_CH2_LEFT:  Określa, że pin 30 portu rozszerzeń (P9) steruje kierunkiem obrotu lewego koła przedniego;

PIN_DIR_CH3_LEFTOkreśla, że pin 17 portu rozszerzeń (P8) steruje kierunkiem obrotu prawego koła tylnego;

PIN_DIR_CH4_LEFT:  Określa, że pin 15 portu rozszerzeń (P8) steruje kierunkiem obrotu lewego koła tylnego.

MAX_SPEED: Jest to stała przechowująca aktualną maksymalną prędkość jaką można ustawić dla platformy (czyli jak ustawię ją na 100% [100] to platforma powinna się poruszać jakieś 1 może 1,5 km/h).

MIN_SPEED:  Jest to stała przechowująca minimalną prędkość jaką można ustawić dla platformy (czyli jak ustawię ją na 23% - 25% platforma powinna się praktycznie nie poruszać). Metodą prób i błędów ustaliłem, że w zasadzie na wartościach ustawionych poniżej 23 - 25 nie ruszymy platformą z miejsca :) - uważajcie więc, żeby nie spalić kontrolera i silniczków.

CHANGE_RATE: Jest to stała określająca wartość z jaką, czy też o jaką zwiększamy lub zmniejszamy prędkość (wartość ta to oczywiście % wypełnienia naszego sygnału podawanego z BBB do kontrolera silniczków). Domyślnie jest 5 ale można poeksperymentować z innymi mniejszymi lub większymi :).

STOP_SPEED: Jest to wartość jaką ustawiamy na wyjściu kiedy chcemy aby robot się zatrzymał.

FORWARD_DIR: Wartość definiująca kiedy robot ma jechać do przodu (jazda do przodu).

REVERSE_DIR: Wartość definiująca kiedy robot ma jechać do tyłu (jazda do tyłu).

Tak wygląda zdefiniowanie stałych sterujących w programie. Teraz należałoby zdefiniować zmienne globalne dla bieżącego kierunku.
Zmienne te będą śledziły, aktualną prędkość i kierunek naszego robota.
Pierwsza z tych definicji jest o tyle ważna, że inicjowane są definiowane są w niej piny na portach rozszerzeń które chcemy używać do kontroli naszej maszyny.
Inna sprawa, że sporo się nakombinowałem zanim znalazłem odpowiedni obraz Debiana, który ma wszystko ustawione prawidłowo ale nie będę tu teraz o tym pisał.
Ważne jest to, że używając funkcji PWM.start() dla odpowiednio: PIN_SPEED_CH1_RightPIN_SPEED_CH2_LeftPIN_SPEED_CH3_Right oraz PIN_SPEED_CH4_Left - inicjujemy po prostu przypisane do tych stałych pinouty PWM, naszego BeagleBone Black.
W dokładnie taki sam sposób użyjemy funkcji zmiennej GPIO.setup() dla pinów PIN_DIR_CH1_RightPIN_DIR_CH2_LeftPIN_DIR_CH3_Right oraz PIN_DIR_CH4_Left do inicjalizacji pinów cyfrowych Input/Output naszego komputera (to one będą zbierały sygnał z enkoderów i na jego podstawie program "podejmie decyzje" jak kręcić nimi dalej).
Dodatkowo w programie została założona funkcja init_rover(), którą jak Zobaczycie będziemy wywoływali przed wywołaniem każdej innej funkcji w tym programie.
W następnym poście (bo teraz już mi się nie chce), omówię pozostałe funkcje i pokrótce ich działanie.

A na koniec coś dla wszystkich zadufanych w technologii, wszechwiedzących, badających sedno wszystkiego i wszystkich, drążących prawdę w poszukiwaniu prawdy, która... jest szara jak szynszyla i rozczarowuje:

"Gdy
już nakarmię swoje ego
galaktyk
i harmonii pyłem
i Głos usłyszę ten
dlaczego
na ziemi
między wami byłem
to skłonię przed Nim
czoło dumne
podam
swą duszę pełną strachu
i
po raz drugi jeszcze umrę
by zostać
na wszechświata dachu"

Ryszard Szociński

czwartek, 23 listopada 2017

Program sterujący "układu jezdnego" :->

Kurde ale trzeba być durniem, żeby pisać blog, który czyta może z pięć osób - porażka...

Dziś przetestowałem układ jezdny. Na razie daleko temu jest do autonomicznego robota ale przy dobrych wiatrach wszystko się może uda... jakoś.

W moim ostatnim poście, próbowałem pokazać Wam drodzy czytelnicy jak można połączyć platformę BeagleBone Black z podwoziem produkowanym przez DAGU, czyli - Rover'em 5.
Do połączenia i sterowania silnikami DC użyłem dedykowanej do tego zestawu elektroniki czyli kontrolera silników DAGU.
Cóż jeszcze - wykonałem krótki test, prostym programikiem napisanym w Pythonie i pomęczyłem się z niedziałającymi obrazami systemu Debian, który w tym komputerku "siedzi" i jego konfiguracją - sporo tego było - niemal miesiąc ślęczenia praktycznie w miejscu i związanej z tym frustracji :(

Jeśli ktoś mnie teraz zapyta czy przyszedł czas na udanie się do "WC dla personelu" to - nie będzie w błędzie. Otóż podczas pisania tego tekstu chorowałem na tak zwaną "jelitówkę" i generalnie oprócz osłabienia, przesiadywałem głównie w "Świątyni dumania", więc miałem sporo czasu na myślenie :-D Pomiędzy posiedzeniami tam gdzie "Król chadza bez korony", wykorzystywałem swój wolny czas (a taki wolny czas jest cenny), bowiem pozwoliło na dalsze prace nad platformą i ostateczne poprawki w napisanym kodzie programu sterującego w Pythonie, oraz programu, który przetestuje moje założenia i mniej więcej jak będzie wyglądało sterowanie robotem.
Zastanawiam się tylko czy nie być "rasowym Cebulakiem" i udostępnić kod pospólstwu i tak chyba zrobię :-)
Każdy wie, że każda maszyna cyfrowa (w tym komputer robota) nie umie nic bez oprogramowania. Należy więc zdefiniować podstawowe ruchy maszyny jak np.: jazda do przodu, do tyłu, skręcanie w prawo i lewo, przyśpieszanie, zwalnianie itd. itp. Oczywiście założyłem, że zmęczę to wszystko w Pythonie, bowiem jest bardzo dużo ciekawych przykładów po sieci i zawsze czegoś nowego się dowiem. :)
W tej części przedstawiam moduł sterujący robotem. Plik dla przykładu nazwałem: rover_beaglebone_v2.py.
Wersja 2 bo przymiarki i kombinacje z tym jak to uruchomić już od nieomal wakacji uskuteczniałem, no i skutkiem tych "prac koncepcyjno - studialnych" => (ale suchar :/) - powstały w sumie trzy wersje tego programu różnie działające, mniej lub bardziej zadawalające mnie. Ta ostatnia "v2" (nie mylić z niemieckimi rakietami do zabijania von Brauna) to efekt właśnie posiedzeń na "batyskafie" w towarzystwie kolegów rotawirusów :)
Oczywiście dokładnie też postaram się opisać co i jak działa ale to może już nie w tym poście... tylko w następnym - bo tak i już ha ha :)
Kod programu:
  1. import Adafruit_BBIO.PWM as PWM
  2. import Adafruit_BBIO.GPIO as GPIO
  3. import time

  4. PIN_SPEED_CH1_Right = "P9_14"
  5. PIN_SPEED_CH2_Left = "P9_16"
  6. PIN_SPEED_CH3_Right = "P8_19"
  7. PIN_SPEED_CH4_Left = "P8_13"
  8. PIN_DIR_CH1_Right = "P9_27"
  9. PIN_DIR_CH2_Left = "P9_30"
  10. PIN_DIR_CH3_Right = "P8_17"
  11. PIN_DIR_CH4_Left = "P8_15"
  12. MAX_SPEED = 100
  13. MIN_SPEED = 23
  14. CHANGE_RATE = 5
  15. STOP_SPEED = 0
  16. FORWARD_DIR = 1
  17. REVERSE_DIR = 0

  18. current_speed_CH1_Right = STOP_SPEED
  19. current_speed_CH2_Left = STOP_SPEED
  20. current_speed_CH3_Right = STOP_SPEED
  21. current_speed_CH4_Left = STOP_SPEED
  22. current_dir_CH1_Right = FORWARD_DIR
  23. current_dir_CH2_Left = FORWARD_DIR
  24. current_dir_CH3_Right = FORWARD_DIR
  25. current_dir_CH4_Left = FORWARD_DIR

  26. #zainicjowanie ruchu podwozia ROVER ustawienie stanu pinów
  27. def init_rover():
  28. PWM.start(PIN_SPEED_CH1_Right, 0)
  29. PWM.start(PIN_SPEED_CH2_Left, 0)
  30. PWM.start(PIN_SPEED_CH3_Right, 0)
  31. PWM.start(PIN_SPEED_CH4_Left, 0)
  32. GPIO.setup(PIN_DIR_CH1_Right, GPIO.OUT)
  33. GPIO.setup(PIN_DIR_CH2_Left, GPIO.OUT)
  34. GPIO.setup(PIN_DIR_CH3_Right, GPIO.OUT)
  35. GPIO.setup(PIN_DIR_CH4_Left, GPIO.OUT)

  36. def stop_rover():
  37. all_stop()

  38. #funkcja pomocnicza - sprawdza utrzymanie predkosci obrotowej kol

  39. def check_speed(speed):
  40. if speed < MIN_SPEED and speed != STOP_SPEED:
  41. speed = MIN_SPEED
  42. if speed > MAX_SPEED:
  43. speed = MAX_SPEED
  44. return speed

  45. def fastest_speed_front(): 
  46. global current_speed_CH1_Right, current_speed_CH2_Left
  47. ret_speed_front = current_speed_CH1_Right
  48. if current_speed_CH2_Left > current_speed_CH1_Right:
  49. ret_speed_front = current_speed_CH2_Left
  50. return ret_speed_front

  51. def fastest_speed_rear():
  52. global current_speed_CH3_Right, current_speed_CH4_Left
  53. ret_speed_rear = current_speed_CH3_Right
  54. if current_speed_CH4_Left > current_speed_CH3_Right:
  55. ret_speed_rear = current_speed_CH4_Left
  56. return ret_speed_rear

  57. def slowest_speed_front():
  58. global current_speed_CH1_Right, current_speed_CH2_Left
  59. ret_speed_front = current_speed_CH1_Right
  60. if current_speed_CH2_Left < current_speed_CH1_Right:
  61. ret_speed_front = current_speed_CH2_Left
  62. return ret_speed_front

  63. def slowest_speed_rear():
  64. global current_speed_right_CH3_Right, current_speed_CH4_Left
  65. ret_speed_rear = current_speed_CH3_Right
  66. if current_speed_CH4_Left < current_speed_CH3_Right:
  67. ret_speed_rear = current_speed_CH4_Left
  68. return ret_speed_rear

  69. #set speed - ustaw predkosci kol
  70. def set_right_speed_wheel_front(speed): #prawa gasienica kolo przednie
  71. global current_speed_CH1_Right, current_speed_CH2_Left
  72. new_speed = check_speed(speed)
  73. PWM.set_duty_cycle(PIN_SPEED_CH1_Right,new_speed)
  74. current_speed_CH1_Right = new_speed

  75. def set_right_speed_wheel_rear(speed): #prawa gasienica kolo tylne
  76. global current_speed_CH3_Right, current_speed_CH4_Left
  77. new_speed = check_speed(speed)
  78. PWM.set_duty_cycle(PIN_SPEED_CH3_Right,new_speed)
  79. current_speed_CH3_Right = new_speed

  80. def set_left_speed_wheel_front(speed): #lewa gasienica kolo przednie
  81. global current_speed_CH1_Right, current_speed_CH2_Left
  82. new_speed = check_speed(speed)
  83. PWM.set_duty_cycle(PIN_SPEED_CH2_Left,new_speed)
  84. current_speed_CH2_Left = new_speed

  85. def set_left_speed_wheel_rear(speed): #lewa gasienica kolo tylne
  86. global current_speed_CH3_Right, current_speed_CH4_Left
  87. new_speed = check_speed(speed)
  88. PWM.set_duty_cycle(PIN_SPEED_CH4_Left,new_speed)
  89. current_speed_CH4_left = new_speed

  90. def set_speed(speed):
  91. set_right_speed_wheel_front(speed)
  92. set_right_speed_wheel_rear(speed)
  93. set_left_speed_wheel_front(speed)
  94. set_left_speed_wheel_rear(speed)
  95.     
  96. #Increase speed - Zwekszenie predkosci
  97. def increase_right_speed_wheel_front(): #prawa gasienica kolo przednie
  98. global current_speed_CH1_Right, current_speed_CH2_Left
  99. set_right_speed_wheel_front(current_speed_CH1_Right + CHANGE_RATE)

  100. def increase_right_speed_wheel_rear(): #prawa gasienica kolo tylne
  101. global current_speed_CH3_Right, current_speed_CH4_Left
  102. set_right_speed_wheel_rear(current_speed_CH3_Right + CHANGE_RATE)

  103. def increase_left_speed_wheel_front(): #lewa gasienica kolo przednie
  104. global current_speed_CH1_Right, current_speed_CH2_Left
  105. set_left_speed_wheel_front(current_speed_CH2_Left + CHANGE_RATE)

  106. def increase_left_speed_wheel_rear(): #lewa gasienica kolo tylne
  107. global current_speed_CH3_Right, current_speed_CH4_Left
  108. set_left_speed_wheel_rear(current_speed_CH4_Left + CHANGE_RATE)

  109. def increase_speed():
  110. increase_right_speed_wheel_front()
  111. increase_right_speed_wheel_rear()
  112. increase_left_speed_wheel_front()
  113. increase_left_speed_wheel_rear()

  114. #Decrease speed - Zmniejszenie predkosci
  115. def decrease_right_speed_wheel_front(): #prawa gasienica kolo przednie
  116. global current_speed_CH1_Right, current_speed_CH2_Left
  117. set_right_speed_wheel_front(current_speed_CH1_Right - CHANGE_RATE)

  118. def decrease_right_speed_wheel_rear(): #prawa gasienica kolo tylne
  119. global current_speed_CH3_Right, current_speed_CH4_Left
  120. set_right_speed_wheel_rear(current_speed_CH3_Right - CHANGE_RATE)

  121. def decrease_left_speed_wheel_front(): #lewa gasienica kolo przednie
  122. global current_speed_CH1_Right, current_speed_CH2_Left
  123. set_left_speed_wheel_front(current_speed_CH2_Left - CHANGE_RATE)

  124. def decrease_left_speed_wheel_rear(): #lewa gasienica kolo tylne
  125. global current_speed_CH3_Right, current_speed_CH4_Left
  126. set_left_speed_wheel_rear(current_speed_CH4_Left - CHANGE_RATE)

  127. def decrease_speed():
  128. decrease_right_speed_wheel_front()
  129. decrease_right_speed_wheel_rear()
  130. decrease_left_speed_wheel_front()
  131. decrease_left_speed_wheel_rear()

  132. #Set direction forward - Ustawianie kierunku do przodu
  133. def forward_right_dir_wheel_front(): #naprzod przednie kolo prawe
  134. global current_dir_CH1_Right, current_dir_CH2_Left
  135. if current_dir_CH1_Right == REVERSE_DIR:
  136. all_stop()
  137. GPIO.output(PIN_DIR_CH1_Right, GPIO.HIGH) #LOW
  138. current_dir_CH1_Right = FORWARD_DIR

  139. def forward_right_dir_wheel_rear(): #naprzod tylne kolo prawe
  140. global current_dir_CH3_Right, current_dir_CH4_Left
  141. if current_dir_CH3_Right == REVERSE_DIR:
  142. all_stop()
  143. GPIO.output(PIN_DIR_CH3_Right, GPIO.LOW)
  144. current_dir_CH3_Right = FORWARD_DIR

  145. def forward_left_dir_wheel_front(): #naprzod przenie kolo lewe
  146. global current_dir_CH1_Right, current_dir_CH2_Left
  147. if current_dir_CH2_Left == REVERSE_DIR:
  148. all_stop()
  149. GPIO.output(PIN_DIR_CH2_Left, GPIO.HIGH)
  150. current_dir_CH2_Left = FORWARD_DIR

  151. def forward_left_dir_wheel_rear(): #naprzod tylne kolo lewe
  152. global current_dir_CH3_Right, current_dir_CH4_Left
  153. if current_dir_CH4_Left == REVERSE_DIR:
  154. all_stop()
  155. GPIO.output(PIN_DIR_CH4_Left, GPIO.LOW)
  156. current_dir_CH4_Left = FORWARD_DIR

  157. def forward_dir():
  158. forward_right_dir_wheel_front()
  159. forward_right_dir_wheel_rear()
  160. forward_left_dir_wheel_front()
  161. forward_left_dir_wheel_rear()
  162. #Set reverse direction - Ustawienie kierunku do tylu
  163. def reverse_right_dir_wheel_front(): #wstecz przednie kolo prawe
  164. global current_dir_CH1_Right, current_dir_CH2_Left
  165. if current_dir_CH1_Right == FORWARD_DIR:
  166. all_stop()
  167. GPIO.output(PIN_DIR_CH2_Left, GPIO.LOW) # HIGH
  168. current_dir_CH1_Right = REVERSE_DIR

  169. def reverse_right_dir_wheel_rear(): #wstecz tylne kolo prawe
  170. global current_dir_CH3_Right, current_dir_CH4_Left
  171. if current_dir_CH3_Right == FORWARD_DIR:
  172. all_stop()
  173. GPIO.output(PIN_DIR_CH4_Left, GPIO.HIGH)
  174. current_dir_CH3_Right = REVERSE_DIR

  175. def reverse_left_dir_wheel_front(): #wstecz przednie kolo lewe
  176. global current_dir_CH1_Right, current_dir_CH2_Left
  177. if current_dir_CH2_Left == FORWARD_DIR:
  178. all_stop()
  179. GPIO.output(PIN_DIR_CH1_Right, GPIO.LOW) # HIGH
  180. current_dir_CH2_Left = REVERSE_DIR

  181. def reverse_left_dir_wheel_rear(): #wstecz tylne kolo lewe
  182. global current_dir_CH3_Right, current_dir_CH4_Left
  183. if current_dir_CH4_Left == FORWARD_DIR:
  184. all_stop()
  185. GPIO.output(PIN_DIR_CH3_Right, GPIO.HIGH) #or HIGH
  186. current_dir_CH4_Left = REVERSE_DIR

  187. def reverse_dir():
  188. reverse_right_dir_wheel_front()
  189. reverse_right_dir_wheel_rear()
  190. reverse_left_dir_wheel_front()
  191. reverse_left_dir_wheel_rear()

  192. #Stop rover - Zatrzymanie rovera
  193. def stop_left_wheel_front():
  194. set_left_speed_wheel_front(STOP_SPEED)

  195. def stop_left_wheel_rear():
  196. set_left_speed_wheel_rear(STOP_SPEED)

  197. def stop_right_whell_front():
  198. set_right_speed_wheel_front(STOP_SPEED)

  199. def stop_right_wheel_rear():
  200. set_right_speed_wheel_rear(STOP_SPEED)

  201. def all_stop():
  202. stop_left_wheel_front()
  203. stop_left_wheel_rear()
  204. stop_right_whell_front()
  205. stop_right_wheel_rear()

  206. #Full speed - Cala naprzod
  207. def full_speed_left_wheel_front():
  208. set_left_speed_wheel_front(MAX_SPEED)

  209. def full_speed_left_wheel_rear():
  210. set_left_speed_wheel_rear(MAX_SPEED)

  211. def full_speed_right_wheel_front():
  212. set_right_speed_wheel_front(MAX_SPEED)

  213. def full_speed_right_wheel_rear():
  214. set_right_speed_wheel_rear(MAX_SPEED)

  215. def all_full_speed():
  216. full_speed_left_wheel_front()
  217. full_speed_left_wheel_rear()
  218. full_speed_right_wheel_front()
  219. full_speed_right_wheel_rear()

  220. #Spin rover - Obracanie rovera - skrecanie - zawracanie
  221. def spin_right(speed):
  222. all_stop()
  223. forward_dir()
  224. forward_right_dir_wheel_front()
  225. forward_right_dir_wheel_rear()
  226. reverse_left_dir_wheel_front()
  227. reverse_left_dir_wheel_rear()
  228. set_right_speed_wheel_front(speed)
  229. set_right_speed_wheel_rear(speed)
  230. set_left_speed_wheel_front(speed)
  231. set_left_speed_wheel_rear(speed)

  232. def spin_left(speed):
  233. all_stop()
  234. forward_dir()
  235. forward_left_dir_wheel_front()
  236. forward_left_dir_wheel_rear()
  237. reverse_right_dir_wheel_front()
  238. reverse_right_dir_wheel_rear()
  239. set_right_speed_wheel_front(speed)
  240. set_right_speed_wheel_rear(speed)
  241. set_left_speed_wheel_front(speed)
  242. set_left_speed_wheel_rear(speed)
Rozumiecie??? :-D Widzicie??? :-D
No to jak rozumiecie i widzicie to wszystko po kolei wyjaśnię:)
Do kontroli pinów z tak zwanych przeze mnie "hederów" P8 i P9 BBB, używam biblioteki Adafruit BBIO omówionej parę postów wcześniej.
Ale ponieważ już nie chce mi się pisać więcej to resztę omówię przy okazji następnego postu.
Łostańcie z Bogiem.

sobota, 18 listopada 2017

Testy połączeń platformy, o linuxie i trochę konfigurowania stuffu :)

Okej na początek fotka 
Czas na sprawdzenie teorii w praktyce i pierwszy test układu jezdnego
Dla celów testowych umieszczamy nasze podwozie na czymś co spowoduję niestykanie się rolek napędowych z powierzchnią i demontujemy gąsienice.
Na razie przecież nie chcemy, aby nasza platforma odjechała, tym bardziej, że póki co mamy komputer BeagleBone Black podpięty do komputera przez UART.
Później się będę zastanawiał jak rozwiążę zdalne przesyłanie oprogramowania i ewentualnych modyfikacji do platformy. Na razie szczerze mówiąc nie mam pojęcia jak to zrobić - ale nie pali się:)

Dobra czas na kod. Na początek napisałem prosty skrypt "na cztery koła" nazywając go np. test.py - wy możecie sobie go nazwać jak wam się żywnie podoba:

import Adafruit_BBIO.PWM as PWM

import time
pin1 = "P9_14"
pin2 = "P9_16"
pin3 = "P8_19"

pin4 = "P8_13"

PWM.start(pin1,0)
PWM.start(pin2,0)
PWM.start(pin3,0)
PWM.start(pin4,0)
PWM.set_duty_cycle(pin1, 100)
PWM.set_duty_cycle(pin2, 100)
PWM.set_duty_cycle(pin3, 100)
PWM.set_duty_cycle(pin4, 100)
time.sleep(60)
PWM.stop(pin1)
PWM.stop(pin2)
PWM.stop(pin3)
PWM.stop(pin4)
PWM.cleanup()

Jeśli wszystko jest prawidłowo połączone i zasilane, to koła powinny obracać się parami "ku sobie" przez czas jaki założymy w zmiennej time.sleep() w moim przypadku to np. 60, czyli minuta czasu :)
Pliki programów moim zdaniem najlepiej umiejscowić sobie w następującym katalogu:
/var/lib/cloud9/nazwa_katalogu - ta ostatnia to wg życzenia.
Narzędzie Cloud9 będzie wtedy łatwo znajdowało nasze programy i nie trzeba będzie się kopać po plikach i katalogach. Oczywiście, jak kto jest bardziej biegły w temacie to może to sobie zrobić w inny sposób. Ja zrobiłam jak umiałem :)
Oczywiście pliki te warto sobie co jakiś czas kopiować na PC np. za pomocą programu WinScp, aby w razie jakiejś awarii, konieczności instalacji wszystkiego od nowa mieć kopię zapasową swojej pracy:)

Do poprawnej pracy potrzebujemy jeszcze biblioteki Adarfuit PWM, którą można zainstalować stosując instrukcje zamieszczone tutaj:


lub tutaj:


Adafruit BBIO jest to taki zestaw narzędzi napisanych w Pythonie i ciągle aktualizowanych, które służą do obsługi i dostępu do konfiguracji  pinów  GPIO, PWM, ADC oraz UART w tej platformie.
Nie wiem dokładnie jak funkcjonują wszystkie te narzędzia więc proszę, jeśli ktoś to czyta nie pytajcie mnie o to. Generalnie konfiguracja standardowa, powinna się znaleźć w każdym aktualnym obrazie Debiana wspierającym tą platformę.
Ja osobiście zalecam używanie jak najbardziej aktualnego obrazu Debiana dla tej płytki dostępnego na przykład na Beaglebone.org w zakładce "Latest Software Images".
Do tego obrazu zaleca się instalację jądra w wersji 4.14.x, po to aby włączyć kontrolę nad konfiguracją GPIO i PWM z poziomu innego użytkownika niż /root - ot choćby to to aby móc swobodnie korzystać z platformy programistycznej Cloud9 "wszytej" w ten obraz, która korzysta jedynie z uprawnień standardowego usera.
Na dzień dzisiejszy ja osobiście używam takiego kernela:

root@beaglebone:~# uname -a
Linux beaglebone 4.4.91-ti-r136 #1 SMP Thu Nov 2 02:28:07 UTC 2017 armv7l GNU/Linux

Wziętego stąd:


Jakkolwiek Developerzy zalecają na dzień dzisiejszy Debiana w wersji 9,2 "Stretch" iot z (2017-10-29), ja mam wersję z nieco nowszym kernelem i wszystko działa bez zarzutu - przynajmniej na razie :)

Myliłby się jednak ten kto by sądził, że poszło to wszystko tak pięknie, ładnie i zgrabnie. Zanim udało się odpalić ten prosty programik - test, co jest powyżej, dobry miesiąc testowałem razem z developerami wskazane przez nich różne testy, polecenia i konfiguracje obrazów, zanim pojawił się obraz, który działa sensownie i stabilnie.
Nie będę wszystkiego tu opisywał szczegółowo, bo uczciwie mówiąc nie jestem jakimś Linux'owym guru, ale koniec końców udało się i wszystko działa.

W tym miejscu chciałbym podziękować panom z github.com - Drew Fustini'emuRobertowi C Nelson'owi za pomoc i wyjaśnienie zawiłości oraz wskazanie co i jak zrobić :)
Co jeszcze? Aha, nowe wersje Adafruit_BBIO mogą być kompatybilne wstecznie ale, jak ktoś chce to niech testuje już we własnym zakresie:)

Poniżej przedstawiam film z jednego z pierwszych testów platformy:
To tyle na dziś. Trzymta się ludziska :)