Skocz do zawartości
Komentator

Kurs Arduino - #4 - Przetwornik ADC

Pomocna odpowiedź

@Treker 

Czy do zad 4.6 wykorzystanie funkcji map (), pomoże czy też wydłuży moją pracę?

Pytam bo nie chce się męczyć na marne i nie potrzebnie pójść w tą stronę.

Udostępnij ten post


Link to post
Share on other sites
Dnia 3.03.2019 o 23:54, Treker napisał:

@jogaszu teraz rozumiem. W takim razie najprościej będzie tuż po wciśnięciu przycisku odczytać wszystkie dane, które są w buforze i nic z nimi nie zrobić (tylko pobrać z bufora, aby go wyczyścić). Spróbuj pójść w tym kierunku 🙂

Hmm jako początkujący teraz ja nie do końca rozumiem. Czy jest jakieś specjalne polecenie pobrania z bufora? Czy po prostu trzeba dopisać jakąś funkcję, która zabierze dane i nic z nimi nie zrobi?

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

Mam cos takiego ale dziala tylko przy okreslonych wartosciach/oswietleniu.

Wydaje mi sie ze jak sie cos we funkcjach pokombinuje to cos z tego moze byc.

Co by tu naprawic? Czy w ogole zrezygnowac z funkcji map ? 🙄

#define zolta1 13
#define zolta2 4
#define czerwona1 12
#define czerwona2 7
#define niebieska 8

int fot1=0; //Fotorezystor 1
int fot2=0; //Fotorezystor 2


void setup() 
{
  Serial.begin(9600); //Przesylanie do terminalu

  pinMode(zolta1, OUTPUT);
  pinMode(zolta2, OUTPUT);
  pinMode(czerwona1, OUTPUT);
  pinMode(czerwona2, OUTPUT);
  pinMode(niebieska,OUTPUT);

}

void loop() 
{
  Serial.print("Fotorezystor 1: ");
  Serial.println(fot1);
  Serial.print("Fotorezystor 2: ");
  Serial.println(fot2);
  delay(500);
  
  fot1=analogRead(A4);
  fot1=map(fot1, 200, 460, 1, 5);
  fot2=analogRead(A5);
  fot2=map(fot2, 230, 605, 1, 5);

  if((fot1 == 5 )&&(fot2 <= 2))
  {
    digitalWrite(zolta1, HIGH); 
    digitalWrite(czerwona1, LOW); 
    digitalWrite(niebieska, LOW); 
    digitalWrite(czerwona2, LOW); 
    digitalWrite(zolta2, LOW);
  }
  else if((fot1<=5)&&(fot2==3))
  {
    digitalWrite(zolta1, LOW); 
    digitalWrite(czerwona1, HIGH); 
    digitalWrite(niebieska, LOW); 
    digitalWrite(czerwona2, LOW); 
    digitalWrite(zolta2, LOW);
  }
  else if(fot1==fot2)
  {
    digitalWrite(zolta1, LOW); 
    digitalWrite(czerwona1, LOW); 
    digitalWrite(niebieska, HIGH); 
    digitalWrite(czerwona2, LOW); 
    digitalWrite(zolta2, LOW);
  }
  else if((fot2<=5)&&(fot1==3))
  {
    digitalWrite(zolta1, LOW); 
    digitalWrite(czerwona1, LOW); 
    digitalWrite(niebieska, LOW); 
    digitalWrite(czerwona2, HIGH); 
    digitalWrite(zolta2, LOW);
  }
  else if((fot2==5)&&(fot1<=2))
  {
    digitalWrite(zolta1, LOW); 
    digitalWrite(czerwona1, LOW); 
    digitalWrite(niebieska, LOW); 
    digitalWrite(czerwona2, LOW); 
    digitalWrite(zolta2, HIGH);
  }
}

 

00000PORTRAIT_00000_BURST20190306152141138.jpg

Edytowano przez arek2007100
zly kod

Udostępnij ten post


Link to post
Share on other sites

A co ma do tego map?

1) Nie masz obsadzonych wszystkich możliwości fot1/fot2 - konkretniej par [(1, 2), (1, 4), (2, 1), (2, 4), (4, 1), (4, 2), (4, 5), (5, 4)]

2) map nie gwarantuje, że wynik będzie ograniczony do podanego zakresu (czyli równie dobrze może być zero albo siedem).

Coś takiego:
 

fot1=map(fot1, 200, 460, 1, 5);
fot1 = constrain(fot1, 1, 5);

zagwarantuje że fot1 będzie w granicach 1 do 5 włącznie.

Pamiętaj, że constrain to makrodefinicja a nie funkcja, czyli zapis typu:

fot1 = constrain(map(fot1, 200, 460, 1, 5), 1, 5);

co prawda będzie działać, ale funkcja map może być niepotrzebnie wywołana dwukrotnie!

 

  • Lubię! 2

Udostępnij ten post


Link to post
Share on other sites
Dnia 5.03.2019 o 22:28, jogaszu napisał:

Czy jest jakieś specjalne polecenie pobrania z bufora? Czy po prostu trzeba dopisać jakąś funkcję, która zabierze dane i nic z nimi nie zrobi?

Możesz wykorzystać Serial.readStringUntil('\n') lub coś innego typu Serial.read() - w tym przypadku nie będzie to miało większego znaczenia. Drugie rozwiązanie będzie bardziej uniwersalne. Tutaj znajdziesz więcej na ten temat: https://www.arduino.cc/reference/en/language/functions/communication/serial/read/

Udostępnij ten post


Link to post
Share on other sites

Witam, po pierwsze chciałbym pochwalić ten kurs, coś niesamowitego, prosty i wyrazisty 🙂 A Po drugie potrzebuje pomocy z zadaniem 4.5 😞 . Oto kod (cześciowy) niecałego zadania 4.5.

#define red 12
#define yellow 11
#define green 10
#define button 8

int odczytanaWartosc = 0;
long pobranaWartosc = 0;
int roznica = 0;
String haslo = "";
int proby = 3;

void setup(){
  for(int i = 10; i <=12 ; i++){
    pinMode(i, OUTPUT);
    digitalWrite(i, LOW);
  }

  pinMode( button, INPUT_PULLUP);
  Serial.begin(9600);
}

void loop(){
  Serial.println("Nastaw potencjometr i wcisnij przycisk");
  
  while(digitalRead(button) == HIGH){} //petla po to żeby nie wykonywał się kod dopóki nie zostanie naciśnięty klawisz
  
  delay(1000);//żeby nie wyłapało zakłóceń od klawisza
  
  Serial.println("Podaj liczbe:");
  
  if(Serial.available()){
    odczytanaWartosc = analogRead(A5);
    pobranaWartosc = Serial.read();
    Serial.println(pobranaWartosc);
    Serial.println(odczytanaWartosc);
    delay(5000); //po prostu opóźnienie dla mnie
  }
  }

Ale w czym problem? Na początku pojawia się na Monitorze "Nastaw potencjometr i wcisnij przycisk" i tak jak było zamierzone program czeka na wciśniecie klawisza, jednakże po jego wciśnięciu wyświetla się tylko kominukat "Podaj liczbe:" i po 5 sek od razu wykonuje ponownie pętle loop() bez pobrania wartości , co więcej nawet nie wyświetla tych wartości jaky pomijał to co jest w IF-ie. Z góry Dziękuję za pomoc 🙂 i Miłego dnia!

Udostępnij ten post


Link to post
Share on other sites
Dnia 20.03.2019 o 00:19, Majtas napisał:

Witam, po pierwsze chciałbym pochwalić ten kurs, coś niesamowitego, prosty i wyrazisty 🙂

Dziękuję za miłe słowa, cieszę się, że kurs jest pomocny 🙂

Dnia 20.03.2019 o 00:19, Majtas napisał:

Na początku pojawia się na Monitorze "Nastaw potencjometr i wcisnij przycisk" i tak jak było zamierzone program czeka na wciśniecie klawisza, jednakże po jego wciśnięciu wyświetla się tylko kominukat "Podaj liczbe:" i po 5 sek od razu wykonuje ponownie pętle loop() bez pobrania wartości , co więcej nawet nie wyświetla tych wartości jaky pomijał to co jest w IF-ie.

Program działa dokładnie tak jak go opisałeś, bo właśnie tak został napisany. Zwróć uwagę, że po wyświetleniu komunikatu proszącego o podanie liczby nie czekasz na jej wpisanie. Właściwie od razu sprawdzasz czy została podana (robisz to tak szybko, że człowiek nie ma szans wpisać wcześniej swojej propozycji). Pomyśl jak można to rozwiązać lepiej - np. za pomocą pętli while, która "opóźni" działanie programu do momentu odebrania danych 🙂

Udostępnij ten post


Link to post
Share on other sites
(edytowany)
#define red 8
#define blue 7
#define prz 9
String typedNumber = "";
byte voltage = 0;
boolean sent = false;
void setup() {
  Serial.begin(9600);
  pinMode(prz, INPUT_PULLUP);
  pinMode(red, OUTPUT);
  pinMode(blue, OUTPUT);

}

void loop() {
  voltage = analogRead(A5);
  if(digitalRead((prz) == LOW)){
    if (sent == false){
    Serial.println("insert number");
    sent = true;
    if(Serial.available() > 0){
      typedNumber = Serial.readStringUntil('\n');
      if(typedNumber == voltage){
        digitalWrite(blue, HIGH);
        
      }else{
        digitalWrite(red, HIGH);
      }
    }
   
  }
  }
}

Mam problem z tym kodem. Chcę ,aby wysyłał komunikat dopiero po wciśnięciu przycisku, a nie od razu w momencie włączenia monitora portu szeregowego. Próbowałem też zmieniać sposób wpinania przycisku i wartość z high na low, ale nic się nie zmieniło.Jestem tu nowy więc z góry dziękuję za pomoc.

Edytowano przez CARRUS17

Udostępnij ten post


Link to post
Share on other sites

@CARRUS17 opisz proszę własnymi słowami jak według Ciebie działa ten program, bo mam wrażenie, że robi coś innego niż chciałeś 🙂 Jak dokładnie podłączyłeś przycisk? Tam nie ma zbyt dużego pola do manewru, w takiej sytuacji jest praktycznie tylko "jedna słuszna wersja".

Udostępnij ten post


Link to post
Share on other sites
2 minuty temu, Treker napisał:

@CARRUS17 opisz proszę własnymi słowami jak według Ciebie działa ten program, bo mam wrażenie, że robi coś innego niż chciałeś 🙂 Jak dokładnie podłączyłeś przycisk? Tam nie ma zbyt dużego pola do manewru, w takiej sytuacji jest praktycznie tylko "jedna słuszna wersja".

Chciałem aby program w wypadku kiedy jest wciśnięty przycisk wyświetlił jednorazowo komunikat "insert number" i sprawdził, czy wpisana liczba jest zgodna z odczytem potencjometru. Jeżeli te liczby by się zgadzały, wtedy powinna zapalić się niebieski led. Jeśli byłyby różne, wtedy żółty led. Co do podłączenia nie mam niestety możliwości aby wysłać teraz zdjęcie. Jeżeli nie da się tego naprawić kodem, będę szukał problemu w podłączeniu.

Udostępnij ten post


Link to post
Share on other sites

Program w obecnej formie jest błędny, ale mam nadzieję, że uda Ci się dojść krok, po kroku do rozwiązania 🙂

Upewnij się najpierw, że samo reagowanie na przycisk działa poprawnie. Usuń zbędę fragmenty kodu i zostaw tylko taki mechanizm, który będzie sprawdzał czy przycisk jest wciśnięty, a jeśli tak to włączy diodę. Później dodaj do tego UART.

Udostępnij ten post


Link to post
Share on other sites

Witam, wykonałem zadanie 4.6, problem jest w tym, że ten program nie jest zoptymalizowany, i nie za bardzo wiem co tutaj mógłbym wrzucić/ zmienić aby był taki ambitny. Byłbym wdzięczny za wszelkie rady i uwagi 🙂

//projekt z fotorezystorami po ktorej stronie jest zrodlo swiatla
int rezystorPrawa = 0;
int rezystorLewa = 0;

#define PRAWA 13
#define PRAWAM  12
#define SRODEK 11
#define LEWAM 10
#define LEWA 9

void setup() {
  Serial.begin(9600);

  for(int i =13; i>8;i--)
  {
    pinMode(i,OUTPUT); 
    digitalWrite(i,LOW); 
  }
}

void loop() {
  rezystorPrawa = analogRead(A4);
  rezystorLewa = analogRead(A5);

  if( rezystorPrawa < 150 ){
    digitalWrite(LEWA, HIGH);
    digitalWrite(LEWAM, LOW);
    digitalWrite(SRODEK, LOW);
    digitalWrite(PRAWAM, LOW);
    digitalWrite(PRAWA, LOW);
  }
  if( rezystorPrawa > 170 && rezystorPrawa < 240 ){
    digitalWrite(LEWA, LOW);
    digitalWrite(LEWAM, HIGH);
    digitalWrite(SRODEK, LOW);
    digitalWrite(PRAWAM, LOW);
    digitalWrite(PRAWA, LOW);
  }
  if( rezystorPrawa < 320 && rezystorPrawa >260){
    digitalWrite(LEWA, LOW);
    digitalWrite(LEWAM, LOW);
    digitalWrite(SRODEK, HIGH);
    digitalWrite(PRAWAM, LOW);
    digitalWrite(PRAWA, LOW);
  }
  if( rezystorPrawa < 410 && rezystorPrawa >330 ){
    digitalWrite(LEWA, LOW);
    digitalWrite(LEWAM, LOW);
    digitalWrite(SRODEK, LOW);
    digitalWrite(PRAWAM, HIGH);
    digitalWrite(PRAWA, LOW);
  }
  if( rezystorPrawa > 420 ){
    digitalWrite(LEWA, LOW);
    digitalWrite(LEWAM, LOW);
    digitalWrite(SRODEK, LOW);
    digitalWrite(PRAWAM, LOW);
    digitalWrite(PRAWA, HIGH);
  }
  
}

 

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

@Majtas jeśli chcesz coś zmieniać to proponowałbym zacząć od wykorzystania funkcji map. Możesz np. obliczyć różnicę wskazań między lewym i prawym fotorezystorem, a następnie, za pomocą funkcji map zamienić ją na liczbę z zakresu od 1 do 5. Wartość tą będzie można później wykorzystać jako informację na temat numeru diody, która powinna świecić.

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Postąpiłem wg. wskazań. Dzięki za pomoc 🙂 Pomógł byś też zastosować jakieś zabezpieczenia? Mam na myśli zniwelowanie stanów nieustalonych. Kiedy przesuwam latarką w jedną stronę w tej samej odległości od płytki, sa momenty, że diody "cofaja się" na moment i potem już normalnie program działa według założeń. Jakby był jakiś moment niedokładnego przełączenia. Co powiesz na ten temat? Aktualny kod:

//projekt z fotorezystorami po ktorej stronie jest zrodlo swiatla
int rezystorPrawa = 0;
int rezystorLewa = 0;
int roznica = 0;
int fotRezPrawOdn = 0;
int fotRezLewOdn = 0;

#define PRAWA 9
#define PRAWAM 10
#define SRODEK 11
#define LEWAM 12
#define LEWA 13

void setup() {
  Serial.begin(9600);

  for(int i =13; i>8;i--)
  {
    pinMode(i,OUTPUT); 
    digitalWrite(i,LOW); 
  }
  fotRezPrawOdn = analogRead(A4);
  fotRezLewOdn = analogRead(A5);
  Serial.println("Prawa strona odniesienie: ");
  Serial.println(fotRezPrawOdn);
  Serial.println("Lewa strona odniesienie: ");
  Serial.println(fotRezLewOdn);
}
//
void loop() {
  rezystorPrawa = analogRead(A4);
  rezystorLewa = analogRead(A5);
//
//  Serial.println("Prawa strona: ");
//  Serial.println(rezystorPrawa);
//  Serial.println("Lewa strona: ");
//  Serial.println(rezystorLewa);
  
  roznica = rezystorPrawa - rezystorLewa;
  roznica = map(roznica, -450, 450, 1,5);
 
  roznica+=8;
if(rezystorPrawa > (fotRezPrawOdn +20) && rezystorLewa > (fotRezLewOdn + 20))
{
  if( roznica == 13 ){
    digitalWrite(LEWA, HIGH);
    digitalWrite(LEWAM, LOW);
    digitalWrite(SRODEK, LOW);
    digitalWrite(PRAWAM, LOW);
    digitalWrite(PRAWA, LOW);
  }
  if( roznica == 12 ){
    digitalWrite(LEWA, LOW);
    digitalWrite(LEWAM, HIGH);
    digitalWrite(SRODEK, LOW);
    digitalWrite(PRAWAM, LOW);
    digitalWrite(PRAWA, LOW);
  }
  if( roznica == 11){
    digitalWrite(LEWA, LOW);
    digitalWrite(LEWAM, LOW);
    digitalWrite(SRODEK, HIGH);
    digitalWrite(PRAWAM, LOW);
    digitalWrite(PRAWA, LOW);
  }
  if( roznica == 10 ){
    digitalWrite(LEWA, LOW);
    digitalWrite(LEWAM, LOW);
    digitalWrite(SRODEK, LOW);
    digitalWrite(PRAWAM, HIGH);
    digitalWrite(PRAWA, LOW);
  }
  if(  roznica == 9){
    digitalWrite(LEWA, LOW);
    digitalWrite(LEWAM, LOW);
    digitalWrite(SRODEK, LOW);
    digitalWrite(PRAWAM, LOW);
    digitalWrite(PRAWA, HIGH);
  }
}
else{
  digitalWrite(LEWA, LOW);
    digitalWrite(LEWAM, LOW);
    digitalWrite(SRODEK, LOW);
    digitalWrite(PRAWAM, LOW);
    digitalWrite(PRAWA, LOW);
}
  
  
}

 

Udostępnij ten post


Link to post
Share on other sites

@Majtas trochę nie rozumiem tego programu. Dlaczego skalujesz sobie wynik na zakres od 1 do 5, a później dodajesz do niego 8? Jaki w tym cel? Jak już dojdziesz do ładu z tym tematem to proponowałbym np. zamienić te if'y na jeden switch-case. Będzie wyglądało ładniej 😉

14 godzin temu, Majtas napisał:

Kiedy przesuwam latarką w jedną stronę w tej samej odległości od płytki, sa momenty, że diody "cofaja się" na moment i potem już normalnie program działa według założeń. Jakby był jakiś moment niedokładnego przełączenia. Co powiesz na ten temat?

Możesz dla testu wprowadzić w programie jakieś małe opóźnienie (typu 20-100 ms) i sprawdź czy to nie poprawi jego działania. Jeśli nie, to możesz jeszcze wykonywać kilka pomiarów i obliczać średnią wartość. Wtedy dane będą bardziej wiarygodne.

  • Lubię! 1

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...