Skocz do zawartości
DevTomek

AVR-IplaTV-Box v2, czyli Ipla TV na Twoim telewizorze!

Pomocna odpowiedź

Po analizie sugestii użytkowników jakie pojawiły się pod pierwszą wersję projektu, postanowiłem rozbudować projekt o zewnętrzny moduł IR tym samym zastępując wykorzystany wcześniej zestaw Atnel ATB  na Arduino Nano 🙂

avr-iplatv-box---zamieniamy-zestaw-atnel-atb-na-arduino.thumb.jpg.8d4d6f89cd9171fe1a0a5768f43c2506.jpg

Migracja z zestawu ATB do Arduino

Proces migracji z ATB do Arduino był stosunkowo prosty, ponieważ głównym zadaniem tego zewnętrznego modułu jest odczytywanie komend IR z pilota i przesyłanie ich do komputera. Biorąc pod uwagę fakt, że każde Arduino jest wyposażone w układ pozwalający na komunikację UART<->USB, proces developmentu sprowadził się w głównej mierze do doboru bibliotek, których w sieci jest bardzo dużo.

Dodatkowa rozbudowa - LCD

Podczas tworzenia zewnętrznego modułu IR postanowiłem również zaimplementować wyświetlacz LCD 2x16 ze sterownikiem HD44780 w celu wyświetlania dodatkowych informacji o aktualnie oglądanym programie TV. Niestety nie posiadałem konwertera HD44780<->I2C, który pozwala na sterowanie tym wyświetlaczem przy użyciu 4 przewodów (w tym 2 zasilających). W rezultacie, w środku urządzenia znajduje się dużo przewodów połączeniowych.

avr-ipla-tv-box-arduino--front.thumb.jpg.533a5b749ea0c2fea127ab15592c491d.jpg avr-ipla-tv-box-arduino--back.thumb.jpg.88858f1446fd352a4d01edd9e91c1beb.jpg 

avr-ipla-tv-box-arduino--inside.thumb.jpg.1c940c4a98c2db91c5a118f654093ee2.jpg

Hardware

Jeśli chodzi o część sprzętową modułu, to składa się ona z Arduino Nano, wyświetlacza LCD HD44780, odbiornika IR TSOP31236 oraz kilku biernych elementów elektronicznych. Do budowy korpusu modułu wykorzystałem niepotrzebne etui na okulary (eco-friendly xD). Poniżej zamieszczam schemat elektryczny oraz połączeniowy modułu, który został stworzony przy użyciu darmowego programu Fritzing.

avr-ipla-tv-box-arduino--schem.thumb.png.66c94a90f37f24aefeac7ce5e62d64f8.png avr-ipla-tv-box-arduino--bb.thumb.png.e4ffad6a390ca053dd3550d366340d4c.png

Software

Sam program na Arduino jest stosunkowo prosty i łatwy do analizy. W głównej pętli programu wywoływane są funkcje do odczytu/aktualizacji stanu całej aplikacji oraz jednego przerwania, które nakręca softwarowy timer odpowiedzialny za scrollowanie tekstu na wyświetlaczu.

  • W oprogramowanie modułu można wyróżnić cztery główne stany:
  • Odczyt komend z IR i wysłanie ich do komputera.
  • Odczyt danych z komputera dot. aktualnie oglądanego programu TV.
  • Aktualizacja danych do wyświetlenia na wyświetlaczu LCD - aktualizacja bufora.
  • Wyświetlenie informacji na LCD - scrollowanie.

Scrollowanie tekstu odbywa się w jednym z dwóch trybów. Pierwszy (no force) wyświetla aktualny tekst z bufora, a sam bufor jest aktualizowany dopiero, gdy cała zawartość zostanie wyświetlona (płynne przejście). Drugi tryb (force) wymusza natychmiastową aktualizację bufora, a proces scrollowania zaczyna się od początku. Tryb ‘force’ jest wykorzystywany w momencie zmiany aktualnie oglądanego kanału, natomiast tryb ‘no force’ podczas aktualizacji informacji o aktualnie oglądanym programie (w głównej mierze chodzi o aktualizację postępu aktualnie oglądanego programu wyrażonego w procentach)

/*
   AVR Ipla TV Box.

   version: v1.1.0
   author: DevTomek.pl
*/
#include <LiquidCrystal.h> // LiquidCrystal by Arduino, Adafruit version 1.0.7
#include <IRremote.h> // IRremote by shirriff version 2.2.3

// LED
const int INFO_LED = 13;

// IR
const int IR_SENSOR = 2;
IRrecv irrecv(IR_SENSOR);
decode_results results;

// LCD
const int SCREEN_WIDTH = 16;
const int SCREEN_HEIGHT = 2;
const int RS = 7, EN = 8, D4 = 9, D5 = 10, D6 = 11, D7 = 12;
LiquidCrystal lcd(RS, EN, D4, D5, D6, D7);

// Serial Read
const char READ_DATA_SEPARATOR = '|';
const uint8_t READ_BUFFER_SIZE = 255;
char readBuffer[READ_BUFFER_SIZE];
boolean hasNewData = false;

// Global Variables
String line1 = "AVR-Ipla-TV-Box";
String line1Buffer = line1;
unsigned int line1Length = 16;
String line2 = "    DevTomek    ";
String line2Buffer = line2;
int stringStart, stringStop = 0;
int scrollCursor = SCREEN_WIDTH;
volatile uint8_t timer1 = 0;


void setup() {

  /* Based on: Arduino Timer Interrupts Calculator */
  // TIMER 1 for interrupt frequency 100 Hz:
  cli(); // stop interrupts
  TCCR1A = 0; // set entire TCCR1A register to 0
  TCCR1B = 0; // same for TCCR1B
  TCNT1  = 0; // initialize counter value to 0
  // set compare match register for 100 Hz increments
  OCR1A = 19999; // = 16000000 / (8 * 100) - 1 (must be <65536)
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS12, CS11 and CS10 bits for 8 prescaler
  TCCR1B |= (0 << CS12) | (1 << CS11) | (0 << CS10);
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);
  sei(); // allow interrupts

  Serial.begin(9600);
  Serial.println("Starting initialization...");
  pinMode(INFO_LED , OUTPUT);
  lcd.begin(SCREEN_WIDTH, SCREEN_HEIGHT);
  irrecv.enableIRIn();
  Serial.println("Initialization done!");
}

void loop() {
  readIRData();
  readSerialData();
  updateData();

  if (timer1 > 25) {
    scroll();
    timer1 = 0;
  }

}

ISR(TIMER1_COMPA_vect) {
  timer1++;
}

void readIRData() {
  if (irrecv.decode(&results)) {
    if (results.value != 0xFFFFFFFF) {
      digitalWrite(INFO_LED , HIGH);
      Serial.println(results.value, HEX);
      digitalWrite(INFO_LED , LOW);
    }
    irrecv.resume();
  }
}

void readSerialData() {
  while (hasNewData == false && Serial.available() > 0) {
    static uint8_t ndx = 0;
    char rc = Serial.read();
    if (rc != '\n') {
      readBuffer[ndx] = rc;
      ndx++;
      if (ndx >= READ_BUFFER_SIZE) {
        ndx = READ_BUFFER_SIZE - 1;
      }
    } else {
      readBuffer[ndx] = '\0';
      ndx = 0;
      hasNewData = true;
    }
  }
}

void updateData() {
  if (hasNewData == true) {
    // RX frame structure: [LINE_1_DATA|LINE_2_DATA|IS_FORCE_MODE]
    line1Buffer =  getValue(readBuffer, READ_DATA_SEPARATOR, 0);
    line2Buffer =  getValue(readBuffer, READ_DATA_SEPARATOR, 1);
    boolean isForceMode = getValue(readBuffer, READ_DATA_SEPARATOR, 2) == "true";
    if (isForceMode) {
      updateLcdData();
    }
    hasNewData = false;
  }
}

String getValue(String data, char separator, int index) {
  int found = 0;
  int strIndex[] = {0, -1};
  int maxIndex = data.length() - 1;

  for (int i = 0; i <= maxIndex && found <= index; i++) {
    if (data.charAt(i) == separator || i == maxIndex) {
      found++;
      strIndex[0] = strIndex[1] + 1;
      strIndex[1] = (i == maxIndex) ? i + 1 : i;
    }
  }

  return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}

void scroll() {
  lcd.clear();
  lcd.setCursor(scrollCursor, 0);
  lcd.print(line1.substring(stringStart, stringStop));
  lcd.setCursor(0, 1);
  lcd.print(line2);

  if (stringStart == 0 && scrollCursor > 0) {
    scrollCursor--;
    stringStop++;
  } else if (stringStart == stringStop) {
    updateLcdData(); // update the text as the previous one will be displayed
  } else if (stringStop == line1Length  ) {
    stringStart++;
  } else if (line1Length < SCREEN_WIDTH && stringStop == (SCREEN_WIDTH + line1Length) ) {
    stringStart++;
    stringStop = stringStart;
  } else {
    stringStart++;
    stringStop++;
  }

}

void updateLcdData() {
  stringStart = stringStop = 0;
  scrollCursor = SCREEN_WIDTH;
  line1 = line1Buffer;
  line2 = line2Buffer;
  line1Length =  line1.length();
}

Podsumowanie

Na koniec chciałbym tylko zaznaczyć, że zastosowany na początku projektu zestaw Atnel ATB, był celowym wyborem, ponieważ projekt był wtedy w fazie rozwoju, więc zastosowanie zestawu uruchomieniowego miało jak najbardziej sens. Po długotrwałych testach okazało się, że cały projekt zakończył się sukcesem i wszystko działa zgodnie z moimi oczekiwaniami, co oznaczało że trzeba przejść do kolejnego etapu, czyli stworzenie finalnej wersji urządzenia i zastąpienie zestawu uruchomieniowego, czymś w rodzaju zewnętrznego modułu IR.

Na koniec zamieszczam krótki filmik przedstawiający aktualną wersję mojego urządzenia AVR-IplaTV-Box. Zapraszam również na mojego bloga AVR-IplaTV-Box - zamieniamy zestaw Atnel ATB na Arduino do zapoznania się z wpisem dot. opisanej wyżej migracji. 🙂 

  • Lubię! 2

Udostępnij ten post


Link to post
Share on other sites

Podoba Ci się ten projekt? Zostaw pozytywny komentarz i daj znać autorowi, że zbudował coś fajnego!

Masz uwagi? Napisz kulturalnie co warto zmienić. Doceń pracę autora nad konstrukcją oraz opisem.

Właśnie zaakceptowałem Twój opis, możesz go teraz zgłosić do akcji rabatowej umieszczając link w temacie zbiorczym. Dziękuję za przedstawienie ciekawego projektu, zachęcam do prezentowania kolejnych DIY oraz aktywności na naszym forum 🙂

PS pierwotnie ten post miał być aktualizacją poprzedniego tematu, ale za moja namową publikuję go jako osobne DIY, bo chyba tak będzie rozsądniej. Pierwsza wersja projektu była opisana tutaj:

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites
Dnia 26.10.2019 o 17:22, DevTomek napisał:

zastępując wykorzystany wcześniej zestaw Atnel ATB  na Arduino Nano

Mały krok wykonałeś, w kolejnym pozbądź się całkowicie dodatkowego uC.

  • Nie zgadzam się! 1

Udostępnij ten post


Link to post
Share on other sites

@RFM może w takim razie podzielisz się dobrą radą i zaproponujesz odpowiednie rozwiązanie?

Na pewno wiele osób skorzysta chętnie z rady doświadczonej osoby 🙂 Przypominam o PPFKrytykuj z klasą. Wytykanie błędów też jest potrzebne. Wskaż zauważony błąd i kulturalnie wytłumacz, jak można go rozwiązać. Wykaż się wiedzą i udziel wartościowej porady.

Udostępnij ten post


Link to post
Share on other sites
21 minut temu, RFM napisał:

Mały krok wykonałeś, w kolejnym pozbądź się całkowicie dodatkowego uC.

Proszę rozwiń co masz na myśli pod pojęciem "pozbądź się całkowicie dodatkowego uC"?🙂

Udostępnij ten post


Link to post
Share on other sites
24 minuty temu, DevTomek napisał:

Proszę rozwiń co masz na myśli pod pojęciem "pozbądź się całkowicie dodatkowego uC"?🙂

Odpowiedź masz w temacie na temat pierwszej wersji urządzenia

 

Udostępnij ten post


Link to post
Share on other sites

Ok, tylko nadal nie wiem jak miałbym odczytywać komendy IR bez użycia zewnętrznego modułu? Przecież ten Zotac to jest zwykły komputer bez dodatkowych pinow GPIO itp. 🙂

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Pomysł @Elvis jego trzeba by zapytać 🙂

A jak nie odpowie, to przyznam, że nie spotkałem komputera, który nie miałby GPIO w postaci LPT czy RS232C. Przejrzyj dokumentacje komputera i sprawdź czy nie ma jakiegoś złącza na PCB.

Udostępnij ten post


Link to post
Share on other sites
17 minut temu, RFM napisał:

Pomysł @Elvis jego trzeba by zapytać 🙂

A jak nie odpowie, to przyznam, że nie spotkałem komputera, który nie miałby GPIO w postaci LPT czy RS232C. Przejrzyj dokumentacje komputera i sprawdź czy nie ma jakiegoś złącza na PCB.

Czasy takich portów już dawno odeszły do lamusa tzn. już ich nie ma w nowych komputerach, a tym bardziej w tym. A po drugie, koszty Arduino (dokładnie mówiąc chińskich klonów) i odbiornika IR są tak małe, że nie warto brnąć w takie rozwiązania 🙂

Udostępnij ten post


Link to post
Share on other sites
6 minut temu, DevTomek napisał:

Czasy takich portów już dawno odeszły do lamusa tzn. już ich nie ma w nowych komputerach

W przemysłowych są.

7 minut temu, DevTomek napisał:

a tym bardziej w tym

W tym może faktycznie nie ma.

7 minut temu, DevTomek napisał:

A po drugie, koszty Arduino (dokładnie mówiąc chińskich klonów) i odbiornika IR są tak małe, że nie warto brnąć w takie rozwiązania

Przejściówka USB-RS232C kosztuje ok 5zł.

Udostępnij ten post


Link to post
Share on other sites
5 minut temu, RFM napisał:

W przemysłowych są.

W tym może faktycznie nie ma.

Przejściówka USB-RS232C kosztuje ok 5zł.

Dokładnie, w przemysłowych są takie peryferia, ale w tym nie ma. Odnośnie przejściówki, to sama przejściówka nic nie da, bo trzeba dokupić jeszcze jakiś moduł IR co wiąże się z dodatkowymi kosztami. Ale ogólnie rzecz ujmując to, czy kupowanie gotowych modułów można nazwać czymś rozwojowym i twórczym? Przecież w każdym projekcie chodzi o to, żeby nauczyć się czegoś nowego i jak sama nazwa działu wskazuje (DIY) zrobić coś samemu. Przy produkcji masowej można myśleć o redukowaniu kosztów i wykorzystywaniu gotowych modułów, ale tutaj raczej chodzi o customowe implementacje i swoją wizję rozwiązania danego problemu 🙂 

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Skoro zostałem przywołany do dyskusji to chyba nie mam wyjścia i muszę się wypowiedzieć.

Więc po pierwsze - nie twierdziłem, że na pewno da się i że wiem jak w tym konkretnym systemie zintegrować wszystko na jednym mikroprocesorze. Jeśli się nie da, albo jest za trudno itd. to oczywiście dodanie mikrokontrolera może mieć sens.

Gdy to pisałem bardzo raziło mnie używanie płytek Atnela, bo uważałem że są zbyt drogie, a i nie przepadałem za ich twórcą, bo uważałem że robi kasę na początkujących, chociaż wcale nie ma wiedzy i umiejętności, żeby uczyć innych. Jednak teraz, będąc starszym i mądrzejszym o dyskusje na naszym forum chciałbym się z tego wycofać i bardzo przeprosić M.Kardasia. Nadal mam pewne zastrzeżenia, ale w porównaniu z innymi samoukami w dziedzinie elektroniki i informatyki jest on prawdziwym geniuszem. A co najważniejsze jest normalny i po prostu zarabia tam gdzie ma to sens. Więc przepraszam, zachęcam do używania płytek ATB, brania udziału w zbiórkach na polakpotrafi itd.

Natomiast co do set-top-box'ów, to akurat tego modelu nie znam, ale przy kilku pracowałem i obsługa gpio była dostępna zarówno na platformach intela, jak i ARM-ach. Chociaż bez dostępu do dokumentacji faktycznie może to być trudniejsze, żeby nie powiedzieć niemożliwe do implementacji. Jednak internet, a google w szczególności to dobre źródło informacji - może na ten mikroprocesor są dostępne źródła linuksa oraz niezbędne sterowniki. Warto to sprawdzić zanim użyje się dodatkowych układów.

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

@Elvis zgadzam się z Twoją wypowiedzią i miałem kiedyś takie samo zdanie jak Ty dot. Atnel'a. Co do mojego projektu to widzę, że wśród użytkowników czytający ten oraz poprzedni post jest małe niezrozumienie, bo zastosowany przeze mnie komputer to jest zwykły mini PC, nie jest to żaden ARM jak raspberry pi czy coś w tym stylu. Komputer ten psiada zwykły system Linux mint cinnamon x64 taki sam jaki używam na swoim stacjonarnym komputerze i nie ma on nic wspólnego z komputerami jednoukladowymi 🙂

Udostępnij ten post


Link to post
Share on other sites

@DevTomek Linux dla komputerów stacjonarnych, laptopów i systemów wbudowanych jest absolutnie taki sam. Więc w większości przypadków nawet na stacjonarnym PC można mieć dostęp do GPIO, tylko nic dobrego z tego nie wyjdzie bo piny i tak są podłączone do odpowiednich peryferiów. Ale w większości przypadków nie ma różnicy czy mówimy o komputerze przemysłowym / wbudowanym, stacjonarnym, czy opartym o układ ARM.

Udostępnij ten post


Link to post
Share on other sites

@Elvis mógłbyś tu podlinkować jakieś wartościowe wg. Ciebie materiały edukacyjne dot. linuxa jakiś tutorial albo kurs?  Tak żeby nie czytać darmo lania wody na 700 stron.

Udostępnij ten post


Link to post
Share on other sites

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!

Gość
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...