Skocz do zawartości

Kurs Arduino - #6 - kontynuacja UART, serwomechanizmy


Pomocna odpowiedź

W takim razie wstawiam swoje rozwiązania 🙂

Zadanie 6.1

#define przycisk 8

int potencjometr = 0;
int fotorezystor1 = 0;
int fotorezystor2 = 0;
int wcisnieciePrzycisku = 0;

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

void loop() {
 potencjometr = analogRead(A5);
 fotorezystor1 = analogRead(A3);
 fotorezystor2 = analogRead(A4);

 while(digitalRead(przycisk)==HIGH); ////Program czeka na wciśnięcie przycisku
 delay(500); //Odczekanie dla uniknięcia powielania
 wcisnieciePrzycisku++;  //Po wciśnięciu przycisku zostanie dodana wartość

 Serial.print("Fotorezystor 1: ");
 Serial.print(fotorezystor1);
 Serial.print(", fotorezystor2: ");
 Serial.print(fotorezystor2);
 Serial.print(", potencjometr: ");
 Serial.print(potencjometr);
 Serial.print(", przycisk wcisnieto ");
 Serial.print(wcisnieciePrzycisku);
 Serial.print(" razy.\n");
 Serial.println();
}

Zadanie 6.2

#define czerwona 8
#define zielona 9

int odebraneDane = 0;

void setup() {
 Serial.begin(9600);
 pinMode(czerwona,OUTPUT);
 pinMode(zielona,OUTPUT);

 digitalWrite(czerwona,LOW);
 digitalWrite(zielona,LOW);
}

void loop() {

 while(Serial.available()==0);
 odebraneDane = Serial.read();

 switch(odebraneDane){
   case 'z':
     digitalWrite(zielona,HIGH);
     delay(1000);
     digitalWrite(zielona,LOW);
   break;

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

   default:
     Serial.println("Zle wpisana wartosc.");
   break;
 }

 delay(1000);
}

Zadanie 6.3 (trochę prowizoryczne, ale działa 😋 )

#include <Servo.h>

Servo serwomechanizm; //Obiekt, dzięki któremu możemy odwołać się do serwa
byte pozycja = 0; //0*-180*
int pozycjaPoprzednia = 0;
int odczytCzujnika = 0;
int maksimum = 0;
int minimum = 10000;

void setup() {
 serwomechanizm.attach(10);
 Serial.begin(9600);
}

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

 if(odczytCzujnika > maksimum)
   maksimum = odczytCzujnika;

 if(odczytCzujnika < minimum)
   minimum = odczytCzujnika;
 pozycja = map(odczytCzujnika, 0, 900, 0, 180);

 if(abs(pozycja-pozycjaPoprzednia) > 5){ //Sprawdzamy, czy pozycje różnią się o ponad 5 stopni
   serwomechanizm.write(pozycja); //Wykonujemy ruch
   pozycjaPoprzednia = pozycja; //Zapamiętujemy aktualną pozycję nadpisując poprzednią
 }

 Serial.print("Aktualny odczyt: ");
 Serial.println(odczytCzujnika);
 Serial.print("Maksimum: ");
 Serial.println(maksimum);
 Serial.print("Minimum: ");
 Serial.println(minimum);
 Serial.println();
 delay(1000);
}

Zadanie 6.4

Nie mam niczego specjalnego - zwykły orczyk i mały, kwadratowy prostokąt, ale jak już wstawiam wszystkie zadania, to i zdjęcie wrzucę 😉

Przy okazji: jak można zmienić kierunek obrotu serwa na zgodny ze wskazówkami zegara?

  • 2 tygodnie później...

Zadanie 6.3 i 6.4

Trochę rozwinąłem to zadanie dodając regulację skrajnych wychyleń serwa w celu dopasowania do różnych tarcz. Autokalibracja i regulacja wychylenia jest możliwa w trybie konfiguracyjnym (patrz kod). Niestety, z racji braku kondensatorów (po weekendzie czeka mnie wycieczka do sklepu) nie mogłem dać na serwo zasilania z gniazda Vin, więc podpiąłem je pod gniazdo 5V. Do zasilania wykorzystałem zasilacz impulsowy 12V 2A. Wklejam kod i zdjęcie układu poniżej. Czekam na wszelkie opinie i rady, gdyż jestem nowy w elektronice i każda pomoc się przyda 🙂

/* 
 This program is used to measure current level of light
 and write it to the servomechanism, which is used as 
 a simulation of analog gauge. The program includes the
 configuration mode with autocalibration.

 USE CONFIGURATION MODE BEFORE FIRST USE!
*/

#include <Servo.h> //includes servo library

#define potPin A1 //potentiometer pin
#define lightPin A0 //photoresistor pin
#define switchPin 9 //tact-switch pin
#define servoPin 10 //servo controller pin

Servo servo; //servo initialisation

void setup() {

 pinMode(switchPin, INPUT_PULLUP); //sets switch pin to pull up mode
 servo.attach(servoPin); //attaches servo pin to object
 Serial.begin(9600); //initialisation of serial monitor

}

int minValue = 0; //minimum value of rotation
int maxValue = 180; //maximum value of rotation
int rotationValue = 0; //current rotation value
int previousValue = 0; //previous rotation value
int maxReadValue = 1023; //maximum read value of light in current environment

void loop() {

 //CONFIGURATION MODE
 if (digitalRead(switchPin) == LOW) //if button pushed go into configuration mode
 {
   delay(300); //eliminates bouncing on button

   //ADJUST MINIMUM VALUE
   while (digitalRead(switchPin) == HIGH) //loop until the button is pushed
   {
     rotationValue = analogRead(potPin); //reads potentiometer value
     rotationValue = map(rotationValue, 0, 1023, 180, 90); //maps value to fit the rotation
     servo.write(rotationValue); //writes the rotation to servo to show current setting
     delay(100); //delay for smoother effect
   }
   delay(300); //eliminates bouncing on button
   minValue = rotationValue; //sets chosen value as minimum rotation value

   //ADJUST MAXIMUM VALUE
   while (digitalRead(switchPin) == HIGH)
   {
     rotationValue = analogRead(potPin); //reads potentiometer value
     rotationValue = map(rotationValue, 0, 1023, 0, 90); //maps value to fit the rotation
     servo.write(rotationValue); //writes the rotation to servo to show current setting
     delay(100); //delay for smoother effect
   }
   delay(300); //eliminates bouncing on button
   maxValue = rotationValue; //sets chosen value as maximum rotation value
   rotationValue = 90;

   //AUTOCALIBRATION
   Serial.println("Light measurement started");

   for(int i = 0; i < 50; i++) //loop lasts for 5s -> 50 * 100ms = 5000 ms = 5s
   {
     maxReadValue = analogRead(lightPin); //reads value from photoresistor
     delay(100); //delay for smoother effect
   }

   Serial.println("Light measurement finished");

   maxReadValue *= 2; //doubles maximum read value

   if(maxReadValue > 1023) //if the value is over the maximum supported value
   {
      maxReadValue = 1023; //sets value to maximum supported value
   }

 }

 //NORMAL MODE
 else
 {
   int lightValue = analogRead(lightPin); //reads current photoresistor value
   rotationValue = map(lightValue, 0, maxReadValue, minValue, maxValue); //maps value for rotation

   if (abs(rotationValue - previousValue) > 5) //if the difference of values is bigger than 5 degrees
   {
     servo.write(rotationValue); //writes current rotation value to servo
     previousValue = rotationValue; //sets current value as previous value
     delay(100); //delay for smoother effect
   }

   Serial.println(lightValue); //sends current light value to terminal
   delay(100); //delay for smoother effect

 }

}

__________

Komentarz dodany przez: Treker

  • 1 miesiąc później...

Zadanie 6.1

#define przycisk 7

int potencjometr=0;
int fotorezystor1=0;
int fotorezystor2=0;
int nacisniecia=0;

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

}

void loop() {
  potencjometr=analogRead(A4);
  fotorezystor1=analogRead(A5);
  fotorezystor2=analogRead(A3);

  if(digitalRead(przycisk)==LOW){

     Serial.print("Fotorezystor 1: ");
     Serial.print(fotorezystor1);
     Serial.print("\t Fotorezystor 2: ");
     Serial.print(fotorezystor2);
     Serial.print("\t Potencjometr: ");
     Serial.print(potencjometr);
     nacisniecia+=1;
     Serial.print("\t Nacisniecia: ");
     Serial.print(nacisniecia);
     Serial.print("\n");
     delay(300);

   }
}

Zadanie 6.2

#define zielona 8
#define czerwona 9

int odebraneDane=0; 

void setup() {
 Serial.begin(9600); //Uruchomienie komunikacji
 pinMode(zielona, OUTPUT); //Konfiguracja wyjść
 pinMode(czerwona, OUTPUT);

 digitalWrite(zielona, LOW); //Wyłączamy diody
 digitalWrite(czerwona, LOW);
}

void loop() {
 if(Serial.available() > 0) { //Czy Arduino odebrano dane
                              //Jeśli tak, to odczytujemy je do znaku końca linii i zapisz w zmiennej odebraneDane
   odebraneDane = Serial.read(); 

   switch(odebraneDane){
     case '1':
       digitalWrite(zielona,HIGH);
       delay(1000);
       digitalWrite(zielona, LOW);
     break;
     case '2':
      digitalWrite(czerwona, HIGH); //To włączamy diodę czerwoną
      delay(1000);
      digitalWrite(czerwona, LOW);
     break;
     default:
      Serial.println("Bledny kolor. 1-zielona, 2-czerwona");
     break;

   }
 }
}

Witam,
W sumie to widzę, że w kodach poprzedników jest ten sam "błąd" ale ja jednak chciałbym dowiedzieć się jak to naprawić.

A więc program działa dobrze jeżeli wpiszemy do "szeregowego monitora" jeden znak.

Natomiast jeśli wpiszę np. zxcvbn to zaświeci mi się dioda (bo pierwsza litera to prawidłowe "z" i wyskoczy mi 5 razy, że wpisałem złą liczbę kolejno dla x, c, v, b, n.

Wiecie jak temu zaradzić?

Oto kod:

#define zielona 8
#define czerwona 9

int odebraneDane = 0; //Pusty ciąg odebranych danych

void setup() {
 Serial.begin(9600); //Uruchomienie komunikacji
 pinMode(zielona, OUTPUT); //Konfiguracja wyjść
 pinMode(czerwona, OUTPUT);

 digitalWrite(zielona, LOW); //Wyłączamy diody
 digitalWrite(czerwona, LOW);
}

void loop() 
{
 if(Serial.available() > 0) { //Czy Arduino odebrano dane
   //Jeśli tak, to odczytujemy je do znaku końca linii i zapisz w zmiennej odebraneDane
   odebraneDane = Serial.read(); 


   switch (odebraneDane) { 
     case 'z':  //Jeśli odebrano "z"

       digitalWrite(zielona, HIGH); //To włączamy diodę zieloną
       delay(1000);
       digitalWrite(zielona, LOW); 
     break;

     case 'c':  //Jeśli odebrano "c"

       digitalWrite(czerwona, HIGH); //To włączamy diodę czerwoną
       delay(1000);
       digitalWrite(czerwona, LOW); 
     break;

     default:
       Serial.println("Podano zly kolor, podaj [z] dla diody zielonej");
       Serial.println("[c] dla diody czerwonej");
       break;
   }
 }
}

Razor1996, wszystko się zgadza, program sprawdza po jednej literze, więc każda kolejna interpretowana jest osobno.

  • 3 tygodnie później...
pozycja = map(odczytCzujnika, 0, 900, 0, 180); //Zamieniamy ją na pozycję serwa

Treker mógłbyś mi powiedzieć dlaczego masz wartosć w tej linijce "900"?

piotr1990, wartość taka została dobrana eksperymentalnie. W moim przypadku nigdy wartość odczytana z fotorezystora nie przekraczała ~950 jednostek. Chciałem lepiej wykorzystać zakres ruchu, więc nie rezerwowałem końca skali dla odczytów, które się nigdy nie pojawiały.

  • 3 tygodnie później...

Czy mogę prosić o przetłumaczenie na język ludzki 😅 jednej linijki kodu.

Zrobiłem zadanie domowe nr 6.2

Po wpisaniu litery moje diody migały. Sprawdziłem więc rozwiązania kolegów na forum i okazało się, że kolega Fajeczny zrobił zadanie prawie identycznie. Różnica jest taka:

Ja wpisałem:


if (Serial.available() > 0)
   {
     odebraneDane = Serial.read();
   }

a Fajeczny:


while(Serial.available()==0);
     odebraneDane = Serial.read();

Nie potrafię sobie "przetłumaczyć" instrukcji Fajecznego: "dopóki nie odczytujesz nic..., odczytaj pierwszy znak i wrzuć do zmiennej odebraneDane" ??? Kompletnie się zgubiłem...

Zauważ, że w linii zawierającej while jest średnik. To oznacza, że ciało tej instrukcji jest puste a jej działanie można wytłumaczyć jako: dopóki nie ma żadnego znaku, rób nic (czyli czekaj). Wcięcie w następnej linii jest zupełnie niepotrzebne i zaciemnia obraz. Lepsza byłaby forma:

while(Serial.available()==0)
  {}; 
odebraneDane = Serial.read(); 

wyraźnie pokazująca "pustość" pętli while;

aaa, noo właśnie 😃 Bardzo Ci dziękuję za pomoc teraz już kapuję!

Jeszcze tylko jedna kwestia.

Kolejny problem na jaki natrafiłem to zero odpowiedzi ze strony serwomechanizmu (HD-1370A). Zasłaniam fotorezystor i odsłaniam (wartości od ~900 do ~1010) a servo ani drgnie.

Czy jest to możliwe, że mam założone zbyt duże kondensatory?

Niestety kupiłem w Botlandzie inny zestaw niż przewidziany w kursie... potem dokupiłem zestaw kondensatorów ale okazało się, że nie ma tam wartości uF 😕

Mam więc założone 2 x 100nF...

Szkoda bo jestem zielony i właściwie wszystko na początku sprawia trudności.

Swoją drogą to troszkę irytujące jest doszukiwanie się w każdej lekcji, czy aby na pewno mam właściwy zestaw... Swój zakupiłem właśnie dzięki linkom z lekcji #0. Niestety po kliknięciu, w sklepie Botland pojawiają się cztery zestawy. Który jest właściwy? Ten najdroższy?

Treker a mogę Cię choć prosić, żebyś podał jaki zakres kondensatorów mogę użyć na pewno?

Wiem, że już ktoś o to pytał ale nie mogę znaleźć.

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...