• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Odczyt wejść z ekspandera PCF8574 z wykorzystaniem timera na ESP32
#1
Mam problem z odczytem stanów wejść. 

Domyślnie każde niepodłączone do masy wejście ma przypisany stan wysoki także odczyty powinny być na 1.  Do pierwszego wejścia mam podpiętą masę, dla drugie nie.   Na Serial port otrzymuje taki wynik jak poniżej.   Żeby było ciekawiej jak wyjmę tą funkcję z przerwań i wywołuję z poziomu pętli głównej programu to odczyty są poprawne.   Działa mi też gdy używam biblioteki timer <Timers.h>  . O co tu chodzi? 


input1:0
Input2:1
Input3:1

Natomiast to co odczytuje to:
input1:0
Input2:0
Input3:1
==================  

Kod:
//Kod odczytujący stany wejść na ekspanderze wejść

hw_timer_t * timer = NULL;
int intP1 = 0;
int intP2 = 0;
int intP3 = 0;
#include "PCF8574.h"

TwoWire I2Cone = TwoWire(0);

// Set digital input i2c address
PCF8574 pcf8574_I1(&I2Cone, 0x21, 4, 5);
PCF8574 pcf8574_I2(&I2Cone, 0x22, 4, 5);
//
void IRAM_ATTR ScanKey()
{

        intP1 = pcf8574_I1.digitalRead(P0);
        intP2 = pcf8574_I1.digitalRead(P1);
        intP3 =1;

          Serial.print("input1:" );
          Serial.println(intP1);
          Serial.print("Input2:" );
          Serial.println(intP2);
          Serial.print("Input3:" );
          Serial.println(intP3);
    
}


void setup()
{
  Serial.begin(115200);
  delay(2000);

  pcf8574_I1.pinMode(P0, INPUT);
  pcf8574_I1.pinMode(P1, INPUT);

   Serial.print("Init pcf8574...");
  if (pcf8574_I1.begin()){
    Serial.println("pcf8574_I1_OK");
  }else{
    Serial.println("pcf8574_I1_error");
  }

  Serial.print("Init pcf8574...");
  if (pcf8574_I2.begin()){
    Serial.println("pcf8574_I2_OK");
  }else{
    Serial.println("pcf8574_I2_error");
  }

  timer = timerBegin(0, 80, true);
  timerAttachInterrupt(timer, &ScanKey, false);
  timerAlarmWrite(timer, 500000, true);  // interwal - wpisane 1000000 oznacza co sek. 20000 mikrosekund to 20 ms.
  timerAlarmEnable(timer);
}

void loop()
{


}
 
Odpowiedź
#2
Co do zasady na wejście zawsze musi być coś podłączone, jak nic nie jest podłączone to odczyt jest losowy, zależny od otaczającego wejście pola elektrycznego w powietrzu, zakłóceń.
Jak masz wejście w Arduino i przykładowo podłączasz przycisk, to wybierasz że przycisk jest zwierany do GND, to z drugiej strony podłączasz to wejście przez rezystor 10k do VCC, jak przycisk nie jest wciśnięty to na pinie jest potencjał Vcc, jak jest wciśnięty to przeważa złączenie go z GND i potencjał jest 0.
Możesz przycisk zwierać do Vcc, to wejście "podciągasz" rezystorem pod GND. Nie możesz "podciągnąć" drutem, bo wciśnięcie robiłoby zwarcie, przycisk zamknąłby obwód z GND do VCC, nie może być bardzo duży opór lub jego brak, bo stan będzie nieustalony.
Możesz użyć też odpowiedniej komendy by aktywować w scalaku wewnętrzny rezystor podciągający, niektóre uC mogą mieć PULLUP, rzadziej PULLDOWN, ale nic takiego nie wiedzę w kodzie.
http://akademia.nettigo.pl/starter_kit_030/
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#3
(19-01-2024, 17:07)kaczakat napisał(a): Co do zasady na wejście zawsze musi być coś podłączone, jak nic nie jest podłączone to odczyt jest losowy, zależny od otaczającego wejście pola elektrycznego w powietrzu, zakłóceń.
Jak masz wejście w Arduino i przykładowo podłączasz przycisk, to wybierasz że przycisk jest zwierany do GND, to z drugiej strony podłączasz to wejście przez rezystor 10k do VCC, jak przycisk nie jest wciśnięty to na pinie jest potencjał Vcc, jak jest wciśnięty to przeważa złączenie go z GND i potencjał jest 0.
Możesz przycisk zwierać do Vcc, to wejście "podciągasz" rezystorem pod GND. Nie możesz "podciągnąć" drutem, bo wciśnięcie robiłoby zwarcie, przycisk zamknąłby obwód z GND do VCC, nie może być bardzo duży opór lub jego brak, bo stan będzie nieustalony.
Możesz użyć też odpowiedniej komendy by aktywować w scalaku wewnętrzny rezystor podciągający, niektóre uC mogą mieć PULLUP, rzadziej PULLDOWN, ale nic takiego nie wiedzę w kodzie.
http://akademia.nettigo.pl/starter_kit_030/

To nie o to chodzi.  Odczyty są jak wywołuję z pętli głównej programy. Jak wywołuję za pomocą timera to pojawia się problem.    Tutaj musi mieć to związek z użyciem timera i sposobu wywołania funkcji za jego pomocą.
 
Odpowiedź
#4
(19-01-2024, 17:42)kamil2234 napisał(a): To nie o to chodzi.  Odczyty są jak wywołuję z pętli głównej programy. Jak wywołuję za pomocą timera to pojawia się
problem.    Tutaj musi mieć to związek z użyciem timera i sposobu wywołania funkcji za jego pomocą.

Expander PCF8574 to układ podłaczany przez I2C. To jest szyna szeregowa, niezbyt szybka. W dodatku kontroler I2C też może generować przerwania (oczywiście można go też obsługiwać bez przerwań, z aktywnym czekaniem ale nie wiem jak to wewnętrznie realizuje arduino). Raczej nie rób transferów I2C w przerwaniu, jak już jesteś w przerwaniu to inne czekają. Najwyżej można transfery I2C realizować asynchronicznie i w przerwaniu od timera je startować, a potem w innym przerwaniu (tym od I2C) obsługiwać. Ale nie wiem na ile byłoby to kompatybilne z bibliotekami arduino.
Jak już musić bawić się w przerwania to w przerwaniu od timera ustawiaj jakąś flagę (zmienną) a w loop() ją sprawdzaj i jak jest ustawiona to oczytaj expader i skasuj flagę.
Procedury obsługi przerwań to kod wykonywany na trochę innych prawach niż ten kod właściwy - setup() i loop().
Tak ogólnie grzebanie w jednych urządzeniach w przerwaniach od innych to spory hardcore. Daje się, ale wymaga starannego przemyślenia.
 
Odpowiedź
#5
(19-01-2024, 18:25)oscarX napisał(a):
(19-01-2024, 17:42)kamil2234 napisał(a): To nie o to chodzi.  Odczyty są jak wywołuję z pętli głównej programy. Jak wywołuję za pomocą timera to pojawia się
problem.    Tutaj musi mieć to związek z użyciem timera i sposobu wywołania funkcji za jego pomocą.

Expander PCF8574 to układ podłaczany przez I2C. To jest szyna szeregowa, niezbyt szybka. W dodatku kontroler I2C też może generować przerwania (oczywiście można go też obsługiwać bez przerwań, z aktywnym czekaniem ale nie wiem jak to wewnętrznie realizuje arduino). Raczej nie rób transferów I2C w przerwaniu, jak już jesteś w przerwaniu to inne czekają. Najwyżej można transfery I2C realizować asynchronicznie i w przerwaniu od timera je startować, a potem w innym przerwaniu (tym od I2C) obsługiwać. Ale nie wiem na ile byłoby to kompatybilne z bibliotekami arduino.
Jak już musić bawić się w przerwania to w przerwaniu od timera ustawiaj jakąś flagę (zmienną) a w loop() ją sprawdzaj i jak jest ustawiona to oczytaj expader i skasuj flagę.
Procedury obsługi przerwań to kod wykonywany na trochę innych prawach niż ten kod właściwy - setup() i loop().
Tak ogólnie grzebanie w jednych urządzeniach w przerwaniach od innych to spory hardcore. Daje się, ale wymaga starannego przemyślenia.


Jak mam sterownik na których jest kilkadziesiąt wejść to nie ma wyjścia trzeba obsługiwać wszystkie zdarzenia poprzez przerwania.  Sama inicjalizacja biblioteki nie odbywa się za pomocą przerwań tylko samo wywołanie odczytu, a to różnica.   Co do Ic2 ustawiłem taktowanie magistrali na 400 Mhz spokojnie na takich ekspanderach można nawet ADC do pomiarów odpalić - już to robiłem.  Także do próbkowania wejść co 20 ms w zupełności wystarczy. 

Problem jest gdzieś indziej bo na jednych bibliotekach, ale niektóre wymagają odpalenia procesów w pętli głównej co u mnie odpada. 

Próbuję teraz sił na innych bibliotekach np https://github.com/khoih-prog/ESP32Timer...ree/master no ale sypie błędami
 
Odpowiedź
#6
Obsługa I2C trwa wieczność, przerwanie dla UART to wpisanie kolejnego bajta do bufora nadawczego, trwa nanosekundy, a tu masz te 400kHz i parę bajtów do wysłania, co trwa tysiące razy dłużej, AVR raczej nie ogarnia przerwań w przerwaniach, nie wiem jak to wygląda w ESP32.
Jestem za cienki w programowaniu, stąd zabawa w Arduino, na początek zmienne używane w przerwaniach i w loop, lub w różnych przerwaniach, zrobiłbym volatile.
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości