Arduino Polska Forum
problem w programie Arduino - Wersja do druku

+- Arduino Polska Forum (https://forum.arduinopolska.pl)
+-- Dział: Korzystanie z Arduino (https://forum.arduinopolska.pl/dzial-korzystanie-z-arduino)
+--- Dział: Programowanie w Arduino (https://forum.arduinopolska.pl/dzial-programowanie-w-arduino)
+--- Wątek: problem w programie Arduino (/watek-problem-w-programie-arduino)

Strony: 1 2


problem w programie Arduino - sewek10 - 15-11-2019

Witam, robię sobie projekt, jest to moduł mechanicznej modulacji światła na arduino, steruję wentylatorem 4 pinowym za pomocą pwm zmienionego na 30kHz, do tego mam czujnik szczelinowy który zlicza prędkość, potencjometry do regulacji wypełnienia PWM oraz lcd który pokazuje aktualna prędkość. Problem polega na tym, że wszystko ładnie działa, ale tylko wtedy kiedy pwm jest 100%. Pokazuje wtedy prędkosc 2200 rpm a jak zahamuje wentylator palcem to stopniowo maleje. Gdy zmniejsze wypełnienie pozniej 100% to nagle skacze z 2200 na 3800 a nastepnie stopniowo spada wraz ze mniejszaniem wypełnienia, jednak te wartosci skacza w zakresie 100rpm wiec to i tak jakies bzdury. Juz nie wiem co to moze byc, Timer 1 zlicza predkosc a timer 2 przestawia PWM na 30kHz. Prosze o pomoc


Kod:
#include <LiquidCrystal_I2C.h>
#include "TimerOne.h"
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2);
const byte SpeedSensor = 2;
volatile unsigned int counter = 0;
volatile unsigned int counterStan = 0;
float diskslots = 6;
float Speed = 0;

int timeToWait = 1000; //Czas, który ma czekać
int setTime=0;              
int aktualTime=0;
int done;

int odczytanaWartosc = 0;
void ISR_count()
{
  counter++;
}

void ISR_timerone()
{
  Timer1.detachInterrupt();
  counterStan = counter;
  Speed = (counter / diskslots) * 60.00;
  counter = 0;
  Timer1.attachInterrupt( ISR_timerone );
}
void setup() {

   TCCR2B = TCCR2B & B11111000 | B00000001; // Set PWM for D3 & D11
    pinMode(3, OUTPUT); // Sets the pin as output
 
  Timer1.initialize(1000000);
  attachInterrupt(digitalPinToInterrupt (2), ISR_count, RISING);
  Timer1.attachInterrupt( ISR_timerone);
 
  lcd.init();
  lcd.backlight();
 
}

void loop() {

lcd.clear();
 
  setTime = millis();
  done=1;
  while(done){  //Wykonuje się tak długo aż upłynie 1s i wykona się reszta kodu
    aktualTime = millis();
    if (aktualTime < setTime+timeToWait){
  lcd.setCursor(0,0);
  lcd.print("Frequence: ");
  lcd.print(counterStan);
  lcd.setCursor(0,1);
  lcd.print("RPM: ");
  lcd.print(Speed);
}
else
  {  
    odczytanaWartosc = analogRead(A3);
    analogWrite( 3,(odczytanaWartosc/4));
    done=0;
    }
}
}
[Obrazek: 4189131600_1573848755.png]


RE: problem w programie Arduino - semi - 16-11-2019

Operacje zmiennoprzecinkowe w przerwaniu?
Nie przesadzasz?

Speed w przerwaniu i programie głównym a gdzie volatile?

Nie czyścisz LCD (wiem, wiem, miga) a wyświetlasz wyniki bez formatowania. Zmiana z "100" na np "33" będzie widoczna na LCD w postaci "330". Pewnie dlatego wynik "skacze".
Cytat: nagle skacze z 2200 na 3800 a nastepnie stopniowo spada wraz ze mniejszaniem wypełnienia, jednak te wartosci skacza w zakresie 100rpm
Faktyczna zmiana może być z 22 na 38 albo 220 na 380.


RE: problem w programie Arduino - sewek10 - 16-11-2019

Dodałem volatile do speed, bez zmian. Dałem czyszczenie LCD tez bez zmian. Jak zmienie typ zmiennej float na int w przypadku zmiennej disklots, to wtedy pokazuje predkość co 60 rpm, a nie co 10 jak w przypadku gdy zmienna jest typu float. Nie rozumiem, jak z 220 na 380 ? Przy max wypełnieniu jest doklądnie 2340 rpm, zmniejszam wypełnienie to powinna stopniowo zmniejszac się prędkosc a nagle jest 3800 rpm i pozniej dalej spada.

Jakbym wział dwa arduino i na jednym zrobił zmiane czestotliwosci i regulacje PWM a na drugim zliczanie predkosci i lcd t by działało, a jak te funkcje sa razem to wtedy własnie nie działa.


RE: problem w programie Arduino - elvis - 16-11-2019

Używanie typów zmiennopozycyjnych raz na sekundę to nic złego - ale w tym konkretnym programie faktycznie nie jest konieczne. Popatrz na kod:
Kod:
Speed = (counter / diskslots) * 60.00;

diskslots to stała ma wartość 6.0, czyli Twój kod to w rzeczywistości:

Kod:
Speed = (counter / 6.0) * 60.00;

Gdybyśmy po prostu zastąpili używanie float przez int, to kolejność operacji mnożenia i dzielenia ma znaczenie. Zobaczmy dla przykładu dwie wartości counter: 250 i 251.
Dla 250 mamy:
Speed = (250 / 6) * 60 = 41 * 60 = 2460
A dla 251:
Speed = (251 / 6) * 60 = 41 * 60 = 2460
Problem wynika z dzielenia counter przez 6, które powoduje błąd zaokrąglenia.
Używanie float w tym miejscu pomaga, ale nie jest konieczne - można po prostu zamienić kolejność operacji, najpierw mnożyć, a później dzielić.
Zobaczmy dla 250:
Speed = (250 * 60) / 6 = 2500
Dla 251:
Speed = (251 * 60) / 6 = 2510
Czyli zmieniając kod na:
Kod:
Speed = counter * 60 / diskslots
możesz mięć poprawne wyniki bez używania float.
W rzeczywistości możesz nawet zauważyć, że (60 / diskslots) to po prostu 6.
Czyli można napisać:
Kod:
Speed = counter * (60 / diskslots);

Co będzie odpowiadało po prostu:
Kod:
Speed = counter * 6
Dzięki temu nie tylko rezygnujesz z czasochłonnych operacji na typie float, ale pozbywasz się jeszcze dzielenia.
Nie wydaje mi się żeby to była przyczyna problemów, ale skoro pojawił się wątek float-ach to chciałem krótko podpowiedzieć, jak można się ich pozbyć Smile


RE: problem w programie Arduino - sewek10 - 16-11-2019

Dzięki za wskazówki, bede miec dwie tarcze, jedna 6 otworów a druga 22 wiec ta wartość disklots bedzie zmieniana, ale z tym dzialaniem dobry pomysł Smile


RE: problem w programie Arduino - semi - 16-11-2019

(16-11-2019, 11:58)sewek10 napisał(a): Nie rozumiem, jak z 220 na 380 ?
Wyświetla najpierw 2200 następnie bez kasowania ekranu 38 to zrozumiesz o co mi chodzi.


RE: problem w programie Arduino - sewek10 - 16-11-2019

(16-11-2019, 12:58)semi napisał(a):
(16-11-2019, 11:58)sewek10 napisał(a): Nie rozumiem, jak z 220 na 380 ?
Wyświetla najpierw 2200 następnie bez kasowania ekranu 38 to zrozumiesz o co mi chodzi.
No nie rozumiem, jest 2200  zmniejszam to powinno pokazywac np 2000, to skad 38 ? Poza tym jak hamuje palcem silniczek, to pokazuje prawidłowa predkosc


RE: problem w programie Arduino - Agregacik - 16-11-2019

Masz zasilanie blokowane kondensatorami. Jak wypełnienie 100% to masz w zasadzie pełne napięcie, jak zmniejszasz to siekasz i może stąd jakieś zakłócenia. Przemyśl sposób zasilania, spadki na przewodach zasilających przenoszą się na sygnały.


RE: problem w programie Arduino - sewek10 - 16-11-2019

(16-11-2019, 14:03)Agregacik napisał(a): Masz zasilanie blokowane kondensatorami. Jak wypełnienie 100% to masz w zasadzie pełne napięcie, jak zmniejszasz to siekasz i może stąd jakieś zakłócenia. Przemyśl sposób zasilania, spadki na przewodach zasilających przenoszą się na sygnały.
Spróbuje zasilic czujnik z oddzielnego zasilacza i dam znac o efektach. PS czy ten kondensator jest włozony czy nie to nic nie zmienia


RE: problem w programie Arduino - Agregacik - 16-11-2019

Dobrze jest dawać dwa, elektrolit z 500uF i ceramiczny z 100-500nF. No ale jak sieczka odkłada się na masie wspólnej dla sygnału to kondensator nie pomoże.
Dodam jeszcze.
Nie rozumiem tego:
void ISR_timerone()
{
Timer1.detachInterrupt();
counterStan = counter;
Speed = (counter / diskslots) * 60.00;
counter = 0;
Timer1.attachInterrupt( ISR_timerone );
}
Czy nie wystarczyłoby:
void ISR_timerone()
{
counterStan = counter;
counter = 0;
}
A resztę obliczać w pętli