Skocz do zawartości

Modbus Esp32


robo1973

Pomocna odpowiedź

Witam !!

Obecnie odczytuję cały rejestr holdingowy

0x40000

zmienna1 = modbusTCPServer.holdingRegisterRead(0)

W jaki sposób odczytać tylko jeden bit tego rejestru ? 0 bit i 1 bit ?

0x40000.0

Pozdrawiam !

Edytowano przez robo1973
Link do komentarza
Share on other sites

(edytowany)

W HMI Weintek tak to właśnie działa, dla sterownika SG2/3 TECO to 4x adres_rej.bit

Przykład monitorowania znacznika M32, który zmienia swój stan raz na sekundę. Tabela rejestrów, implementacja dla HMI Weintek.

SG2_adresowanie.thumb.jpg.34a668dadfa8bcb9517c35bef6bc6d92.jpg

Ale.... no właśnie. Dużo zależy od implementacji standardu MODBUS RTU w danym urządzeniu przez producenta. Tak naprawdę trzeba szukać dokumentacji dla danego urządzenia, ponieważ różni producenci różnie implementują standard (tzn. nie zawsze implementują go w 100%)

Edytowano przez BlackJack
Link do komentarza
Share on other sites

(edytowany)

no tak Ale ja używam biblioteki Modbus do esp32

i chcę odczytać  0x40000.0  zerowy bit

zmienna1 = modbusTCPServer.holdingRegisterRead(0x00) >????

Edytowano przez robo1973
Link do komentarza
Share on other sites

(edytowany)
11 minut temu, robo1973 napisał:

no tak Ale ja używam biblioteki Modbus do esp32

i chcę odczytać  0x40000.0  zerowy bit

zmienna1 = modbusTCPServer.holdingRegisterRead(0x00) >????

Myślę że metoda będzie ta sama, tylko ty musisz wpisać to w kodzie, a ja używam programu do panelu.

Z drugiej strony, skoro odczytujesz cały rejestr, to co za problem z niego wyłuskać sobie interesujący cię bit, za pomocą operacji AND. Jak masz już odczytany rejestr, to możesz sobie zrobić z tym co chcesz.

Edytowano przez BlackJack
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

(edytowany)

jeszcze raz spytam

Uruchomiłem serwer Modbus TCP na wt32 ETH01
odczytuję rejestr holdingowy przychodzący z klienta 16 bitów

int SET_PIN_krok_M = modbusTCPServer.holdingRegisterRead(0x00);

W jaki sposób odwołać się do poszczególnych bitów (odczytać wartość bitu 0, 1, 2 do 16 )
Pozdrawiam !!!

Edytowano przez robo1973
Link do komentarza
Share on other sites

ok dzięki za pomoc ale na razie nic z tego nie kumam

odczytuję rejestr 16 bitowy zmienna1 = modbusTCPServer.holdingRegisterRead(0x00)

i co dalej ? Może jakiś początek..

Link do komentarza
Share on other sites

Ok, żeby nie motać, 3 sposoby (pewnie jest ich więcej):

Struktura i wskaźnik, którym pokazujesz w "specyficzny" sposób na swoje 2-bajtowe dane z rejestru (cout, endl, "<<" służą tylko do wypisywania, nie zwracaj na to uwagi):

#include <iostream>
#include <cstdint>
using namespace std;

struct bajty_na_bity { 
	uint16_t _0: 1, _1: 1, _2: 1, _3: 1, _4: 1, _5: 1, _6: 1, _7: 1, _8: 1, _9: 1, _10: 1, _11: 1, _12: 1, _13: 1, _14: 1, _15: 1; 
} typedef bb; // to tylko alias nazwy, skrócony

int main() {
	uint16_t SET_PIN_krok_M = 0xABCD; // 0xABCD (dwa bajty) dla testu, u ciebie to dane z rejestru
	bb * wsk = reinterpret_cast<bb *>(&SET_PIN_krok_M);
	
	// wskaźnikiem odnosisz się do bitów w bajcie
	cout << "bit0: " << wsk ->_0 << endl; 
	cout << "bit1: " << wsk ->_1 << endl;
	cout << "bit2: " << wsk ->_2 << endl;
	cout << "bit3: " << wsk ->_3 << endl;

	return 0;
}

 

Sposób z unią i strukturą; do bitów odnosisz się podając np. ".bit._0"

#include <iostream>
#include <cstdint>
using namespace std;

union bity_na_bajty {
	struct { uint16_t _0: 1, _1: 1, _2: 1, _3: 1, _4: 1, _5: 1, _6: 1, _7: 1, _8: 1, _9: 1, _10: 1, _11: 1, _12: 1, _13: 1, _14: 1, _15: 1; } bit;
	uint16_t bajty;
} typedef bb; // to tylko alias nazwy, skrócony

int main(){
	bb SET_PIN_krok_M;
	SET_PIN_krok_M.bajty = 0xABCD; // 0xABCD (dwa bajty) dla testu, u ciebie to dane z rejestru
	
	// odnosisz się do bitów w bajcie
	cout << "bit0: " << SET_PIN_krok_M.bit._0 << endl;
	cout << "bit1: " << SET_PIN_krok_M.bit._1 << endl;
	cout << "bit2: " << SET_PIN_krok_M.bit._2 << endl;
	cout << "bit3: " << SET_PIN_krok_M.bit._3 << endl;
	// itd
	
	return 0;
}

 

Funkcja z operacjami bitowymi:

#include <iostream>
#include <cstdint>
using namespace std;

int zwroc_bit(uint16_t & rejestr, int8_t bit){
	if(bit < 0 || bit > 15) return -1; // błąd, poza zakresem
	return (rejestr >> bit) & 0x1;
}

int main(){
	uint16_t SET_PIN_krok_M = 0xABCD;
	
	cout << "bit0: " << zwroc_bit(SET_PIN_krok_M, 0) << endl;
	cout << "bit1: " << zwroc_bit(SET_PIN_krok_M, 1) << endl;
	cout << "bit2: " << zwroc_bit(SET_PIN_krok_M, 2) << endl;
	cout << "bit3: " << zwroc_bit(SET_PIN_krok_M, 3) << endl;
	
	return 0;
}

 

Wynik w każdym przypadku:

bit0: 1
bit1: 0
bit2: 1
bit3: 1

 

To samo widać w kalkulatorze, czytając cztery pierwsze bity od prawej (0) do lewej (15):

kalkulator.thumb.jpg.886c9d9b658fc2100a1df2cc95b43190.jpg

Link do komentarza
Share on other sites

@robo1973 , kombinuj, coś wybierzesz.

Chociaż nie wiem, czy jest to po "arduinowemu", ale możesz też stworzyć prostą klasę z przeładowanymi operatorami i odnosić się do bitów rejestru łatwo, za pomocą indeksów. Sposób pewnie trochę przekombinowany i wymagający podstawowej wiedzy o klasach, ale działa. W użyciu skomplikowany nie jest.

#include <Arduino.h>

class bity{
	private:
		volatile uint16_t rejestr;
	public:
		bity() : rejestr(0) {}
		bity(uint16_t rej) : rejestr(rej) {}
		bity & operator = (uint16_t rej){
			rejestr = rej;
			return *this;
		}
		bity & operator += (int x){
			rejestr += x;
			return *this;
		}
		bity & operator -= (int x){
			rejestr -= x;
			return *this;
		}
		int operator [] (int idx) const {
			return (idx < 0 || idx > 15) ? -1 : (rejestr >> idx) & 0x1; // w razie przekroczenia zakresu (0-15) zwracane jest -1
		}
		operator uint16_t() const {
			return rejestr;
		}
};

void setup() {
	Serial.begin(9600);
	while(!Serial);
}

void loop() {
	static bity rejestr = 0xABCD; // tu twój rejestr

	Serial.printf("\n> Wartość rejestru (hex): 0x%4X\n", rejestr);

	// do bitów zmiennej "rejestr" odwołujesz się łatwo poprzez index, np. rejestr[0] to bit0
	// pamiętaj o zakresie 0-15 (czyli 16 bitów), inaczej funkcja zwróci błąd (-1)
	for(int i = 0; i <= 15; i++) Serial.printf("bit[%2i]: %i\n", i, rejestr[i]);

	// testowo, w każdym obiegu pętli, dodaję do rejestru 1:
	rejestr += 1;
	delay(5000);
}

 

Przykładowy wydruk:

> Wartość rejestru (hex): 0xABCD
bit[ 0]: 1
bit[ 1]: 0
bit[ 2]: 1
bit[ 3]: 1
bit[ 4]: 0
bit[ 5]: 0
bit[ 6]: 1
bit[ 7]: 1
bit[ 8]: 1
bit[ 9]: 1
bit[10]: 0
bit[11]: 1
bit[12]: 0
bit[13]: 1
bit[14]: 0
bit[15]: 1

> Wartość rejestru (hex): 0xABCE
bit[ 0]: 0
bit[ 1]: 1
bit[ 2]: 1
bit[ 3]: 1
bit[ 4]: 0
bit[ 5]: 0
bit[ 6]: 1
bit[ 7]: 1
bit[ 8]: 1
bit[ 9]: 1
bit[10]: 0
bit[11]: 1
bit[12]: 0
bit[13]: 1
bit[14]: 0
bit[15]: 1

 

Link do komentarza
Share on other sites

Wszystko działa !! Dziękuję

Chciałbym jeszcze jakoś fajnie zrobić zapisywanie do rejestru modbusTCPServer.inputRegisterWrite(0x00, 0x01);

poszczególnych bitów . Teraz załączam bit najmłodszy .

W zależności od warunku albo podając numery bitów chcę je włączać

Pozdrawiam !

 

Link do komentarza
Share on other sites

@robo1973 , dokończyłem, nawet działa, ale zapomnij o tym. Człowiek czasem <gupi> i walczy jak Don Kichot z wiatrakami, a wystarczyło spojrzeć tu (sekcja: "bity & bajty"): https://www.arduino.cc/reference/pl/

Przykładowo:

void setup() {
	Serial.begin(9600);
	while(!Serial);
}

void loop() {
	uint16_t rejestr = 0xABCD;
	Serial.printf("rejestr przed zmianą: 0x%4X (bit0: %i)\n", rejestr, bitRead(rejestr, 0));

	bitClear(rejestr, 0); // ustawia bit0 na 0
	Serial.printf("rejestr po zmianie: 0x%4X (bit0: %i)\n\n", rejestr, bitRead(rejestr, 0));

	delay(5000);
}

 

Jest też biblioteka standardowa jeżeli arduinów będzie za mało: https://en.cppreference.com/w/cpp/utility/bitset

Link do komentarza
Share on other sites

(edytowany)

Witam !!!

Z Modbus otrzymuję  bit_0 = zwroc_bit(SET_PIN_krok_M, 0)

Chciałbym teraz żeby ten bit wygenerował mi przebieg prostokątny o czasie trwania np 500 ms.

Czyli w chwili gdy pojawia się zbocze narastające (zamiana stanu z 0 n na 1 na bit_0 ) program wygeneruje prostokąt.

Kolejne generowanie prostokąta nastąpi po ponownym pojawianiu się zbocza narastającego na bit_0

Trzeba pewnie odczytywać zbocze narastające na bit_0

Czy jest do tego gotowa funkcja Myślałem o przerwaniach ale one tylko na fizyczne wejścia działają ?

Proszę o pomoc  i dziękuję pozdrawiam !! >

Edytowano przez robo1973
Link do komentarza
Share on other sites

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

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.