Arduino Polska Forum

Pełna wersja: Problematyczna funkcja millis
Aktualnie przeglądasz uproszczoną wersję forum. Kliknij tutaj, by zobaczyć wersję z pełnym formatowaniem.
Witam,

mam problem z programem niby wszystko dział jak należy, ale dziwnie się zachowuje, wygląda mi to na problem z funkcją millis, ale może to jednak coś innego.

A, konkretnie chodzi o port szeregowy i wypisywane w nim wartości z portów analogowych.
Chcę uzyskać na wyjściu portu trzy wartości pomiarowe: napięcia, prądu oraz wartości rezystora -> potencjometru.

Napisałem program i wykorzystałem "funkcję millis". Program niby działa.

Po włączeniu monitora szeregowego zazwyczaj jest dobrze(zielona kreska Pomiar0), ale czasami pierwsza linijka to jakieś artefakty czasami liczby czasami kreski innym razem inne symbole, ale ciekawiej robi się gdy parokrotnie zamknę i wywołam monitor portu szeregowego. Załączyłem parę zdjęć.
Te zdjęcie z zieloną kreską Pomiar0 to prawidłowo działający program (tak jak by chciał) pozostałe, to już wielokrotne wywołanie portu szeregowego.
Sytuacja powtarza się za każdym razem muszę fizycznie odłączyć zasilanie od płytki i pierwsze uruchomienie działa prawidłowo.

Pytanie czy coś przeoczyłem w programie czegoś nie widzę, coś źle napisałem??

Kod:
#define pom_V A3
#define pom_R A5

//Zmienne Globalne
    unsigned long pomiar = 500;

    unsigned long aktualnyCzas = 0;
    unsigned long zapamietanyCzasPom = 0;

    int counter = 0;
    int Up = 13;
    int Down = 12;
    int LED_PWM = 9;
    String text = "";



void setup() {

// inicjacja portów we/wy

      pinMode(A0, INPUT);
      pinMode(pom_V, INPUT);
      pinMode(pom_R, INPUT);
      pinMode(Up, OUTPUT);
      pinMode(Down, OUTPUT);
      pinMode(LED_PWM, OUTPUT);


//Ustawienie dla 20Hz
      TCCR1A = 0;
      TCCR1B = 0;
      TCNT1  = 0;
      TCCR1A = (1<<COM1A1) | (1<<WGM11);
      TCCR1B = (1<<WGM13) | (1<<CS12);      // preskaler 8
      ICR1   = 1499;                     

 
//Uruchomienie portu szeregowego
      Serial.begin(9600);
     

//      while (!Serial)
//      {
//       ;// czekaj na połączenie portu
//      }
}

void loop() {
aktualnyCzas = millis();
//odczyt z portu UART
          if(Serial.available() >0 ){
          text = Serial.readStringUntil('\n');
         
          //Serial.println(text);
         
        
         
//Sterowanie lampki led        
          if(text.equals("on"))
          {
            digitalWrite(Up, HIGH);
          }
          else if(text.equals("off"))
          {
            digitalWrite(Up, LOW);
          }
          else if(text.equals("onn"))
          {
            digitalWrite(Down, HIGH);
          }
          else if(text.equals("offf"))
          {
            digitalWrite(Down, LOW);
          }
          }
       
       
        pom();

    }


void pom(){

              int pomiar_V;
              float napiecie = 4.50;
              float napiecieV;
              //float napieciemodulo;

              int pomiar_R;
              float rezystor = 10.00;
              float rezystancja;
             
//Pobierz liczbe milisekund od startu

              //aktualnyCzas = millis();
              if (aktualnyCzas - zapamietanyCzasPom >=  pomiar)
            {
                zapamietanyCzasPom = aktualnyCzas;

//pomiar wartości analogicznych z czujników

            switch (counter)
            {
              case 0:
                    pomiar_R = analogRead(pom_R);

                    rezystancja = ((pomiar_R / rezystor )* 0.10);
       
                    Serial.println(rezystancja);
              counter ++;
              break;

              case 1:
                    pomiar_V = analogRead(pom_V);

                    napiecieV = ((pomiar_V * napiecie ) / 1024);
        
                    Serial.println(napiecieV);
                counter ++;
                break;

              case 2:

//Czujnik prądu ACS712            
                   unsigned int x=0;
                   float AcsValue=0.0,Samples=0.0,AvgAcs=0.00,AcsValueF=0.0;


//Get 150 samples (Ustawienie 150 próbek)
                   for (int x = 0; x < 150; x++)
                 {
                   AcsValue = analogRead(A0);     //Read current sensor values  
                   Samples = Samples + AcsValue;  //Add samples together
  
                 }
                   AvgAcs=Samples/150.0;          //Taking Average of Samples

                  //((AvgAcs * (4.3 / 1024.0)) is converitng the read voltage in 0-5 volts
                  //2.5 is offset(I assumed that arduino is working on 5v so the viout at no current comes
                  //out to be 2.5 which is out offset. If your arduino is working on different voltage than
                  //you must change the offset according to the input voltage)
                  //0.066v(66mV) is rise in output voltage when 1A current flows at input
                 
                 
                   AcsValueF = 0.3 - (2.5 - (AvgAcs * (5.0 / 1024.0)) )/0.066;
                 
//Print the read current on Serial monitor (wypisanie wartości, prądu na port szeregowy)
                  Serial.println(AcsValueF);
                  counter ++;
                  counter = 0;
                  break;
                 
               
            }
           
        }
       
     }

[attachment=1247]
[attachment=1248]
[attachment=1249]
[attachment=1250]
[attachment=1251]
[attachment=1252]
Dane nie są przekazywane bezpośrednio z Arduino do PC, tylko jest jeszcze konwerter po drodze, może on coś tam generuje, zmień prędkość na 115200.
Zajrzyj też do moich poprzednich postów, niedawno wrzucałem funkcje z millis, (uint32_t) - to może być ważne czasami.
Nie zrobił zrzutowania przy obliczeniach i to może być problem...

pomiar_R = analogRead(pom_R);

rezystancja = ((pomiar_R / rezystor )* 0.10);

Int = analogRead(pom_R);

Float = ((int/float)*float);


Powinno być raczej

rezystancja = (((float)pomiar_R / rezystor )* 0.10);
Może, ale jemu to drukuje w ciągu 1 ms kilka razy, to znaczy, że coś mocno po pamięci mu jeździ albo coś z przepełnianiem bufora UART, albo zmienne w millis nie są rzutowane na (uint32_t).
Przepelnienie stosu też możliwe bardzo w końcu używa float
Dziękuję za podpowiedzi.

W sumie nie brałem pod uwagę, że konwerter może coś dodawać od siebie, a to dlatego, że kupiłem też nadajnik Bluetooth i efekt był ten sam.
Przepełnienie stosu też bałem pod uwagę i kombinowałem z funkcja millis i różnymi zmiennymi, ale efektu pozbyć się nie mogłem.

Po przeczytaniu komentarzy postanowiłem poszukać w swoich zasobach Arduino Mini i mam takie na kontrolerze CH340, bo Adruino Uno na którym, to testowałem będę miał dopiero za tydzień.
I po wgraniu programu okazuje się, że działa. Testowałem chwilę, czy aby na pewno i za każdym razem jest dobrze.
Wprowadziłem też poprawki jeśli chodzi o rzutowanie dziękuję za sugestie.

Mam prośbę jak toś ma płytkę Arduino UNO, to można prosić o przetestowanie programu może z moją płytką jest coś nie tak.

Pytanie czy te dwa procesory czymś się różnią, bo w Mini siedzi Atmega 328P, ale w Uno siedzi ten sam jedynie przewlekany. Zobaczę jeszcze jak będę miał już dostęp do tamtej płytki czy wprowadzone zmiany w obliczeniach coś zmieniły.

Mam jeszcze jedno pytanie, czy jest jakaś prosta możliwość zmiany wyświetlania kropki na przecinek w porcie szeregowym?
Jak jest to błąd sprzętu na tej płytce to nikt tego nie odtworzy na swojej.
W językach programowania używa się kropki, lepiej się do tego przyzwyczaić. Możesz sobie ewentualnie liczby zamieniać na tablice char i podmieniać kropki na przecinki, choć trudne szczególnie to nie jest to sensu większego w tym nie będzie.