Skocz do zawartości

Kurs Arduino - #6 - kontynuacja UART, serwomechanizmy


Komentator

Pomocna odpowiedź

#define timer 150
#define led 8

#include <Servo.h>

Servo mech;
short int posServ = 0;
byte previous = 0;
short int maximum = 190;
byte loopin = 0;

void setup() {
  // put your setup code here, to run once:
  pinMode(10, INPUT_PULLUP);
  pinMode(led, OUTPUT);
  mech.attach(9);
}

void loop() {
  // put your main code here, to run repeatedly:
  posServ = analogRead(A1);
  //mechanism of calibration
  if(digitalRead(10) == LOW){
    digitalWrite(led, HIGH);
    delay(1000);
    while( loopin < 11){
      maximum = analogRead(A1);
      loopin += 1;
      delay(timer);
    }
    digitalWrite(led, LOW);
    loopin = 0; //reset loopin variable
  }
  delay(50);
  posServ = map(posServ, 0 , maximum, 180, 0); //make it in reverse cause scale is inverted
  
  
  if(abs(previous - posServ) > 5){
      mech.write(posServ);
   }
  previous = posServ;
  delay(200);
}

IMG_20220909_120052.thumb.jpg.f36e86318e2125b42573ed63b4717906.jpg

układ z przyciskiem kalibrującym maksymalne światło. Gdy kalibracja zachodzi dioda LED się załącza. W tle moja prowizoryczna tarcza wskaźnik. Przetestowane i działa.

Edytowano przez RakietowyKim
  • Lubię! 1
Link do komentarza
Share on other sites

Na razie 3 zadanka. 🙂

Zad. 6.1

#define przycisk 8 //Przycisk na pin 8

int potek = 0; //Konfiguracja zmiennych
int foto1 = 0;
int foto2 = 0;
int nacisnieciePrzycisku = 0;

void setup() {
  Serial.begin(9600); //Inicjalizacja UART
  pinMode(przycisk, INPUT_PULLUP); //Przycisk na podciaganiu
}

void loop() {
  potek = analogRead(A5); //Przypisanie do zmiennych wartosci odczytanych z pinow
  foto1 = analogRead(A4);
  foto2 = analogRead(A3);

  while(digitalRead(przycisk)==HIGH); //Oczekiwanie na wcisniecie przycisku
  delay(500); //Opoznienie dla zniwelowania zaklocen i drgan
  nacisnieciePrzycisku = nacisnieciePrzycisku + 1;

  Serial.print("Fotorezystor 1:\t");
  Serial.print(foto1);
  Serial.print(", fotorezystor:\t");
  Serial.print(foto2);
  Serial.print(", potencjometr:\t");
  Serial.print(potek);
  Serial.print(", przyisk naciśnięto:\t");
  Serial.print(nacisnieciePrzycisku);
  Serial.print(" razy\n\n");
}

 

Zad. 6.2

#define zielona 9
#define czerwona 8

int polecenie = 0; //Pusty ciąg danych odebranych z UART

void setup() {
  Serial.begin(9600); //Inicjalizacja UART
  Serial.println("Jaką diodę włączyć (z/c)?");
  
  pinMode(zielona, OUTPUT); //Konfiguracja wyjsc
  pinMode(czerwona, OUTPUT);

  digitalWrite(zielona, LOW); //Wylaczenie diod
  digitalWrite(czerwona, LOW);
}

void loop() {
  if(Serial.available() > 0) { //Czy odebrano dane
    polecenie = Serial.read(); //Odczytaj 1 znak z UART
  
    switch (polecenie) { //Wykonaj taki case jaki odebrano znak
    case 'c':
      digitalWrite(czerwona, HIGH); //Wlacz czerwona diode na 1 sek
      Serial.println("Włączono czerwoną diodę.");
      delay(1000);
      digitalWrite(czerwona, LOW);
      Serial.println("Wyłączono czerwoną diodę.");
      Serial.println("Jaką diodę włączyć (z/c)?");
    break;

    case 'z':
      digitalWrite(zielona, HIGH); //Wlacz zielona diode na sek
      Serial.println("Włączono zieloną diodę.");
      delay(1000);
      digitalWrite(zielona, LOW);
      Serial.println("Wyłączono zieloną diodę.");
      Serial.println("Jaką diodę włączyć (z/c)?");
    break;

    default:
      digitalWrite(zielona, HIGH); //zamigaj diodami
      digitalWrite(czerwona, HIGH);
      delay(200);
      digitalWrite(zielona, LOW);
      digitalWrite(czerwona, LOW);
      delay(200);
      digitalWrite(zielona, HIGH);
      digitalWrite(czerwona, HIGH);
      delay(200);
      digitalWrite(zielona, LOW);
      digitalWrite(czerwona, LOW);
      delay(200);
      digitalWrite(zielona, HIGH);
      digitalWrite(czerwona, HIGH);
      delay(200);
      digitalWrite(zielona, LOW);
      digitalWrite(czerwona, LOW);
      Serial.println("Podano niepoprawne polecenie. \n Jaką diodę włączyć (z/c)?");
    break;
    }

    delay(1000);
  }
}

 

Zad. 6.3 Autokalibracja

#include <Servo.h> //Biblioteka od serwa

Servo serwo; //Obiekt odwołujący się do serwa
byte pozycja = 0; //Aktualna pozycja serwa
int pozycjaPoprzednio = 0;
int minimum = 50; //Wartosc minimalna dla odczytu z fotoR
int maximum = 900; //Wartosc maksymalna dla odczytu z fotoR

void setup() {
  serwo.attach(11); //Podlaczenie serwa do pinu z PWM (11)
  Serial.begin(9600);
}

void loop() {
  
  int odczytFoto = analogRead(A5); //Odczyt wartosci ADC z dzielnika
  
  if(odczytFoto < minimum) { //Autokalibracja
  minimum = odczytFoto;
  }
  
  if(odczytFoto > maximum) {
  maximum = odczytFoto;
  }
  pozycja = map(odczytFoto, 100, 900, 170, 10); //Zmiana wartosci ADC na pozycje serwa

  if (abs(pozycja-pozycjaPoprzednio) > 5) { //Sprawdzenie czy roznica pozycji wynosi ponad 5 stopni
    serwo.write(pozycja); //Wykonaj ruch
    pozycjaPoprzednio = pozycja; //Zapamietaj aktualna pozycje jako poprzednia
  }

  Serial.println("Fotorezystor :" + String(odczytFoto));
  delay(300);
}

 

Z zadaniem 6.3 i 6.4 jeszcze wrócę, jak zrobię wskaźnik i dorobię kalibrację ręczną. 🙂

  • Lubię! 1
Link do komentarza
Share on other sites

Interesująca lekcja wraz z ciekawymi zadaniami domowymi 👍

Gdyby ktoś potrzebował pomocy, poniżej podrzucam własne spostrzeżenia oraz działające kody programów do zadań domowych 😉

1️⃣ Zadanie domowe 6.1

#define przycisk 8

int potencjometr = 0;
int fotorezystor_1 = 0;
int fotorezystor_2 = 0;
int ilosc = 0;

void setup() {
  Serial.begin(9600);
  pinMode(przycisk, INPUT_PULLUP);
}

void loop() {
   int potencjometr = analogRead(A3);
   int fotorezystor_1 = analogRead(A4);
   int fotorezystor_2 = analogRead(A5);

   while (digitalRead(przycisk) == LOW) {
    ilosc = ilosc + 1;
    
    Serial.print("Fotorezystor 1: ");
    Serial.print(fotorezystor_1);
    Serial.print("\t");
    Serial.print("Fotorezystor 2: ");
    Serial.print(fotorezystor_2);
    Serial.print("\t");
    Serial.print("Potencjometr: ");
    Serial.print(potencjometr);
    Serial.print("\t");
    Serial.print("Przycisk wcisnieto: ");
    Serial.print(ilosc);
    Serial.print(" razy");
    Serial.println(); //Przejście do nowej linii

    delay(500);
   }
   delay(100);
}

2️⃣ Zadanie domowe 6.2

Wykonując to zadanie polecam trochę poeksperymentować! 😀 Dzięki temu można lepiej zrozumieć, w jaki sposób działa instrukcja switch. Dla przykładu, wystarczy usunąć tylko jedną linijkę kodu (kolor = 0;), przez co program będzie działał kompletnie inaczej. Spróbujcie sami, naprawdę warto! 💪

#define zielona 8
#define czerwona 9
 
String odebraneDane = "";
int kolor = 0;
 
void setup() {
  Serial.begin(9600); 
  pinMode(zielona, OUTPUT); 
  pinMode(czerwona, OUTPUT);
  
  digitalWrite(zielona, LOW);
  digitalWrite(czerwona, LOW);

  Serial.println("Wybierz, ktora dioda ma zostac wlaczona:");
  Serial.println("1. zielona");
  Serial.println("2. czerwona");
  Serial.println();
}
 
void loop() {
  if(Serial.available() > 0) { 
    odebraneDane = Serial.readStringUntil('\n'); 
    
    if (odebraneDane == "zielona") {
      kolor = 1;
    } else if (odebraneDane == "czerwona") {
      kolor = 2;
    } else {
      kolor = 0;  //Wyzerowanie zmiennej kolor!
    }

    switch (kolor) {
      case 1:
        digitalWrite(zielona, HIGH); 
        delay(1000);
        digitalWrite(zielona, LOW);
      break;

      case 2:
        digitalWrite(czerwona, HIGH); 
        delay(1000);
        digitalWrite(czerwona, LOW);
      break;

      default:
      Serial.println("Niewlasciwy kolor!");
      delay(1000);
    }
  }
  delay(100);
}

3️⃣ Zadanie domowe 6.3

W tym zadaniu oprócz wykorzystania dwóch przycisków jako mechanizmu kalibracji, dodałem niezbędne zabezpieczenia, dzięki którym podczas przypadkowego naciśnięcia jednego z przycisków unikniemy "wariacji" serwa 🔒

#include <Servo.h>
#define przyciskMAX 9
#define przyciskMIN 8

Servo serwomechanizm;
byte pozycja = 0;
int pozycjaPoprzednia = 0;

int wartoscMAX = 900; //Początkowa wartość przed kalibracją
int wartoscMIN = 0;   //Początkowa wartość przed kalibracją

int blokadaMAX = 901; //Początkowa wartość blokady
int blokadaMIN = 0;   //Początkowa wartość blokady

void setup() {
  Serial.begin(9600);
  serwomechanizm.attach(11);
  pinMode(przyciskMAX, INPUT_PULLUP);
  pinMode(przyciskMIN, INPUT_PULLUP);
}

void loop() {
  int odczytCzujnika = analogRead(A5);

  //Blokada programu
  ///////////////////////////////////////////////////////////
  
  while (odczytCzujnika > blokadaMAX) {  
    Serial.println("Przekroczono ustawiona wartosc MAX!");
    Serial.println("Zresetuj program!");
    Serial.println();
    delay(3000);
  }

  while (odczytCzujnika < blokadaMIN) {  
    Serial.println("Przekroczono ustawiona wartosc MIN!");
    Serial.println("Zresetuj program!");
    Serial.println();
    delay(3000);
  }

  //Warunki działania programu
  ///////////////////////////////////////////////////////////

  while (digitalRead(przyciskMAX) == LOW) {
    wartoscMAX = odczytCzujnika;
    blokadaMAX = wartoscMAX;                //Zabezpieczenie
    Serial.print("Wartosc maksymalna: ");
    Serial.println(wartoscMAX); 
    delay(1000);
  }

  while (digitalRead(przyciskMIN) == LOW) {
    wartoscMIN = odczytCzujnika;
    blokadaMIN = wartoscMIN;                //Zabezpieczenie
    Serial.print("Wartosc minimalna: ");
    Serial.println(wartoscMIN); 
    delay(1000);
  }
  
  pozycja = map(odczytCzujnika, wartoscMIN, wartoscMAX, 180, 0); //Kalibracja (praca serwa od prawej do lewej)

  if (abs(pozycja-pozycjaPoprzednia) > 5) {
    serwomechanizm.write(pozycja);
    pozycjaPoprzednia = pozycja;
  }
  Serial.print("Wartosc fotorezystora: ");
  Serial.println(odczytCzujnika);
  delay(300);
}
  • Lubię! 1
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

Proszę przeczytać treść całego kursu od początku, linijka po linijce. Znalazłem sporo literówek, nawet zdarzają się losowe słowa w środku zdania. Nie jest to czepialstwo, po prostu mam wrażenie, że kursy podstaw elektroniki I oraz II były bardziej dopracowane. Nie zauważyłem na stronie opcji "zgłoś błędy". Mogę pomóc zlokalizować błędy, ale wydaje mi się, że rzucą się w oczy. Być może autor zredagowałby dziś niektóre rzeczy inaczej :)

  • Lubię! 1
Link do komentarza
Share on other sites

2 godziny temu, LaKukaraczan napisał:

Być może autor zredagowałby dziś niektóre rzeczy inaczej 🙂

@LaKukaraczan potwierdzam 🙂 Ten kurs powstawał w czasach, gdy poradniki były robione bardziej "hobbystycznie", teksty nie przechodziły wtedy przez korektę, trudniej było też o zdjęcia i ilustracje. Tak samo było ze wspomnianymi kursami elektroniki. Tylko, że... kursy elektroniki od tamtego czasu zostały już przepisane praktycznie od nowa (m.in. aby poprawić wszelkie błędy językowe). Takie samo gruntowne odświeżenie czeka ten kurs. Wtedy będzie językowo na takim samym poziomie jak kursy elektroniki. Mam świadomość, że taka aktualizacja jest potrzebna i jest to zaplanowane, aczkolwiek jest to dość duży projekt, więc na ten moment nie podam publicznie jeszcze żadnej daty.

  • Lubię! 1
Link do komentarza
Share on other sites

Podczas próby wykorzystania fotorezystorów natrafiłem na pewien problem. Po napisaniu kodu do zadania 6.3 natrafiłem na problemy z kalibracją układu. Na początku zacząłem podejrzewać, że najpewniej jakość mojego kodu jest przyczyną problemu 🙂 Odczyty z ADC były bardzo niskie (>300) nawet przy oświetlaniu latarką fotorezystora. Problem ustąpił po podmianie fotorezystora na drugi z zestawu. Odczyty z ADC po oświetleniu drugiego fotorezystora skoczyły na ponad 900.

Najdziwniejsze jest to, że wszystko działało poprawnie z kodem zaprezentowanym we wcześniejszych ćwiczeniach. Dla pewności wgrałem tamten kod ponownie i sprawdziłem funkcjonowanie fotorezystora. Wygląda na to, że jego parametry uległy znacznemu pogorszeniu. 

Wykorzystałem miernik dołączony do kursu elektroniki I, aby sprawdzić omomierzem rezystancję obydwu dołączonych do zestawu fotorezystorów. Poniżej zamieszczam zdjęcia z wynikami pomiarów:

IMG20230319115318.thumb.jpg.cf96a40e25d4b23a741004011fb4827b.jpgIMG20230319115259.thumb.jpg.7bfba77e16b4cf5fe7c286a39e063651.jpg

Jak widać pierwszy rezystor, w podobnych warunkach oświetlenia, ma znacznie większą rezystancję (ustawienie na skali omomierza 2000k). Rozbieżność w rezystancji obydwu była wcześniej znacznie mniejsza, bo udało mi się wykonać zadanie 4.6 i ich czułość była zbliżona. 

Co najciekawsze fotorezystor nie został nawet wyjęty z płytki stykowej przed podejściem do zadania 6.3. Czy możliwe, że stracił swoje parametry tak szybko? Być może ja się mogłem poprzez nieuwagę do tego jakoś przyczynić?

Link do komentarza
Share on other sites

@KaroleL ciekawa sprawa, chyba jeszcze nikt nie opisywał takiego problemu. Ogólnie trudno uszkodzić fotorezystory, ale oczywiście jest to możliwe. Może przez jakieś chwilowe błędy w podłączeniu przepłynął przez niego zbyt duży prąd? Jeśli chcesz to jakość obejść to możesz po prostu wykorzystać funkcję map - dzięki niej będziesz mógł przeskalować odczytane wartości. Możesz też zmienić wartość rezystora, który używasz w dzielniku napięcia z tym uszkodzonym fotorezystorem.

Jeśli chcesz to możesz odezwać się również do sprzedawcy zestawu (zapewne Botland) pewnie pomogą i podeślą nowe fotorezystory 😉

  • Lubię! 1
Link do komentarza
Share on other sites

Moje rozwiązanie pracy domowej na 6.1

6.1

// Konfiguracja wejść i wyjść analogowych / cyfrowych pod łatwiejsze nazwy
#define Foto1 A3
#define Foto2 A4
#define Pot A5
#define button 8
//Utworzenie zmiennych
int licznik = 0;
bool wyslano = false;
void setup() {
  Serial.begin(9600); //Rozpoczęcie komunikacji
  pinMode(button, INPUT_PULLUP);//Konfiguracja przycisku
}

void loop() {
  if(digitalRead(button) == LOW) { //Jeśli przycisk wciśnięto
    if(wyslano == false) { // Jeśli wiadomość nie została wysłana
      delay(250); //Delay by zniwelować zakłócenie wynikające z mechanicznego przycisku
      licznik = licznik + 1; //Licznik wciśnięc
      Serial.print("Fotorezystor 1:"); //Tekst
      Serial.print(analogRead(Foto1));//Odczyt wartości
      Serial.print(", Fotorezystor 2:");
      Serial.print(analogRead(Foto2));
      Serial.print(", Potencjonometr:");
      Serial.print(analogRead(Pot));
      Serial.print(", przycisk wciśnięto:");
      Serial.print(licznik);
      Serial.print("\t");
      wyslano = true; //Wiadomość wysłano
    } else {
      wyslano = false;
    }
  }

}

 

  • Lubię! 1
Link do komentarza
Share on other sites

int redPin = 4;
int greenPin = 8;
int odebraneDane=0;
int dt = 1000;

void setup() {
  Serial.begin(9600);
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
}

void loop() {
  if (Serial.available() > 0) {
    odebraneDane = Serial.read();
    Serial.println("What color do you want?");
  }
  switch (odebraneDane) {
    case 'g':
      digitalWrite(greenPin, HIGH);
        delay(dt);
      digitalWrite(greenPin, LOW);
      break;
    case 'r':
      digitalWrite(redPin, HIGH);
        delay(dt);
      digitalWrite(redPin, LOW);
      break;
      default:
      Serial.println("You are wrong");
      delay(dt);
      break;
  }

}

Moje rozwiązanie do zadania 6.2 jednak mam pytanko ponieważ mój program cały czas wysyła mi informację , że źle wpisałem wartość do terminalu nawet jesli nic nie wpisuje. Jak zrobić żeby ta wiadomosc wysyłała się tylko raz??

 

Link do komentarza
Share on other sites

6 godzin temu, hhube napisał:

Jak zrobić żeby ta wiadomosc wysyłała się tylko raz??

Przenieść switch'a do ciała instrukcji if(Serial.available()). Tylko to przy okazji spowoduje inny problem, ale z tym sobie raczej łatwo poradzisz 😉 

Edytowano przez H1M4W4R1
Link do komentarza
Share on other sites

Zadanie 6.3

Aby wejść w tryb kalibracji należy trzymać wciśnięty przycisk podczas resetowania/włączania arduino. Po zapaleniu diody "kalibracja" należy zasłonić fotorezystor aby ustalić minimalny poziom jasności. Po zaświeceniu diody "ledminimum" należy naświetlić fotorezystor aby zmierzyć maksymalny poziom jasności.

#include<Servo.h>
#define pinLDR 4
#define servoPin 10
#define guzikPin 5
#define potencjometr 5
#define LEDminimum 6
#define LEDmaksimum 9
#define LEDkalibracja 8


Servo mojeserwo;
int aktualnaPozycja = 0;
int nowaPozycja = 0;
int LDR = 0;
int minimum = 0;
int maksimum = 0;
int skok = 0;
int roznica = 0;


void setup() 
{
Serial.begin(9600);
mojeserwo.attach(servoPin);
pinMode(guzikPin, INPUT_PULLUP);
pinMode(LEDminimum, OUTPUT);
pinMode(LEDmaksimum, OUTPUT);
pinMode(LEDkalibracja, OUTPUT);

 if(digitalRead(guzikPin) == 0)
{
    digitalWrite(LEDkalibracja, HIGH);

    delay(5000);
    minimum = analogRead(pinLDR);
    Serial.print("Wartosc minimalna to ");
    Serial.println(minimum); 
    Serial.println(""); 
    digitalWrite(LEDminimum, HIGH);

    delay(5000);
    maksimum = analogRead(pinLDR);
    Serial.print("Wartosc maksymalna to ");
    Serial.println(maksimum); 
    Serial.println(""); 
    digitalWrite(LEDmaksimum, HIGH);

    delay(2000);
    digitalWrite(LEDmaksimum, LOW);
    digitalWrite(LEDminimum, LOW);
    digitalWrite(LEDkalibracja, LOW);

}
else
{
  minimum = 1000;
  maksimum = 0;
}
}
void loop() 
{
  LDR = analogRead(pinLDR);
  nowaPozycja = map(LDR, maksimum, minimum, 0, 180);
  //Serial.println(nowaPozycja);
  roznica = abs(aktualnaPozycja - nowaPozycja);

  if(roznica > skok)
  {
   mojeserwo.write(nowaPozycja);
   aktualnaPozycja = nowaPozycja;
  }
 
  delay(10);
}

 

Link do komentarza
Share on other sites

Witam.

Zrobiłem przykład ze światłomierzem i mam pewną zagadkę. 
Rozumiem, że 0% to ciemno a 100% jasno. Dlaczego więc moje serwo ustawia się na "0" kiedy jasno i 100 kiedy ciemno? 
Części posiadam oryginalne z kursu i zrobiłem wszystko jak na przykładzie. Trochę zgłupiałem. 
Jest tak, że gdyby serwo założyć z przodu skali to będzie ok, ale chyba nie o to chodzi i serwo powinno być z tyłu. ;) 
Macie jakiś pomysł? Byłbym wdzięczny. 

Link do komentarza
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!

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.