Stránka 1 z 2
Problém s čtením dat z COM portu (sériová komunikace)
Napsal: 30 bře 2022, 18:44
od vasik006
Zdravím,
snažím se pomocí Arduina vytvořit ovladač pro simulátor a mám problém s čtením výstupu simulátoru. Můj první cíl je rozchodit kontrolku, kterou jsemv programu na získávání informací ze simulátoru definoval písmenem
z, aby se mi při jejím rozsvícením v simulátoru rozsvítila na Arduinu. To se mi už povedlo, ale jakmile ji jednou rozsvítím, tak už ji nezshasnu. Z programu na získávání informací ze simulátoru mám přes COM port výstup z1, z0, z1, z0... Nevím, jak odlišit z0 od z1. Arduino mám pár dnů a žádný programátor nejsem, takže budu rád za každou pomoc. Díky!
Kód: Vybrat vše
void setup() {
Serial.begin(9600);
pinMode(12, OUTPUT);
}
void loop() {
if (Serial.read() == 'z') {
digitalWrite(12, HIGH);
}
}
Re: Problém s čtením dat z COM portu (sériová komunikace)
Napsal: 30 bře 2022, 20:11
od kiRRow
Kód: Vybrat vše
void loop() {
if (Serial.read() == 'z') { // čtu první znak
if (Serial.read() == '1') { // hned za ním čtu druhý
digitalWrite(12, HIGH);
} else { // a pokud ten znak není 1 předpokládám že je 0
digitalWrite(12, LOW);
}
}
}
Re: Problém s čtením dat z COM portu (sériová komunikace)
Napsal: 31 bře 2022, 16:44
od vasik006
Bohužel nefunguje, ani při tomhle se LEDka vůbec nerozsvítí.
Kód: Vybrat vše
void loop() {
if (Serial.read() == 'z') {
digitalWrite(12, HIGH);
} else {
digitalWrite(12, LOW);
}
}
Jinak tady je příklad výstupu z toho programu.
Re: Problém s čtením dat z COM portu (sériová komunikace)
Napsal: 31 bře 2022, 16:49
od vasik006
A tohle taky nic nedělá i kdyby mělo.
Kód: Vybrat vše
void loop() {
if (Serial.read() == 'z') {
if (Serial.read() == '1') {
digitalWrite(12, HIGH);
}
}
}
Re: Problém s čtením dat z COM portu (sériová komunikace)
Napsal: 31 bře 2022, 17:01
od vasik006
Člověk na anglickém fóru mi dal tenhle kód, který sice funguje jak má, ale je strašně složitý.
Kód: Vybrat vše
void setup() {
Serial.begin(9600);
pinMode(12, OUTPUT);
}
void loop() {
static unsigned long serialInTimestamp = 0;
static byte goodData = 0;
if (goodData > 0) {
if (millis() - serialInTimestamp >= 100UL) goodData = 0;
}
if (Serial.available()) {
int c = Serial.read();
if (goodData == 0) {
if (c == 'z') {
serialInTimestamp = millis();
goodData = 1;
}
else goodData = 0;
}
else if (goodData == 1) {
if ( c == '1') {
digitalWrite(12, HIGH);
}
else if ( c == '0') {
digitalWrite(12, LOW);
}
goodData = 0;
}
}
}
Re: Problém s čtením dat z COM portu (sériová komunikace)
Napsal: 31 bře 2022, 17:50
od AstroMiK
Problém je v tom, že když první znak 'z' dorazí po sériové lince těsně před tím prvním Serial.read(), tak ho první Serial.read() sice bez problémů přečte, ale zároveň se tím vyprázdní přijímací buffer.
Když okamžitě po tom následuje další Serial.read(), bude se snažit přečíst druhý znak, který ještě do bufferu nedorazil.
A při pokusu o Serial.read() prázdného bufferu se vrací kód -1 (takže zhasne LED).
Řešení je několik, ale asi nejjednodušší je před ten druhý Serial.read() dát nějakou krátkou pauzu, která zajistí, že bude dost času na příjem druhého znaku.
Při rychlosti 9600 to vychází asi na milisekundu - pro sichr jsem tam dal radši 2 milisekundy.
(v kódu jsem upravil zarovnávání závorek - jsem tak zvyklý a program se mi zdá čitelnější)
Kód: Vybrat vše
void setup(void)
{
Serial.begin(9600);
pinMode(12,OUTPUT);
}
void loop(void)
{
if (Serial.read() == 'z')
{
delay(2);
if(Serial.read() == '1') digitalWrite(12, HIGH);
else digitalWrite(12, LOW);
}
}
Jiné řešení by bylo využívat Serial.available(). A čtení dat provádět až v případě, když je v bufferu předpokládaný počet znaků.
Re: Problém s čtením dat z COM portu (sériová komunikace)
Napsal: 31 bře 2022, 18:52
od vasik006
Děkuji, to je přesně to, co jsem potřeboval.
Jen mám otázku trochu mimo, proč jste napsal u void.setup a void.loop do závorky znovu void?
Re: Problém s čtením dat z COM portu (sériová komunikace)
Napsal: 31 bře 2022, 19:12
od AstroMiK
... někde mě to naučili a tak to tak píšu furt. Význam to ale nemá.
Znamená to, že funkce setup a loop nemají žádné parametry.
Obvykle se ten druhý void nepíše.
Mimochodem ten příklad, který jsem uváděl, by bylo dost obtížné rozšiřovat o další funkce (další znaky - třeba 'x', 'y').
Lepší by bylo si uchovat ten první znak do proměnné a pak ho vyhodnotit buď pomocí několika podmínek
if, nebo pomocí příkazu
switch.
Kód: Vybrat vše
void setup()
{
Serial.begin(9600);
pinMode(10,OUTPUT);
pinMode(11,OUTPUT);
pinMode(12,OUTPUT);
}
void loop()
{
if (Serial.available() > 0)
{
char funkce = Serial.read(); // prvni znak udava funkci ('x', 'y', nebo 'z')
delay(2);
if (funkce == 'x')
{
int parametr = Serial.parseInt(); // za 'x' nasleduje nejake cislo (-32768 az 32767)
if(parametr > 5000) digitalWrite(10, HIGH); // pro vetsi cislo nez 5000 se LED 10 rozsviti
else digitalWrite(10, LOW); // pro mensi cislo LED zhasne
}
if (funkce == 'y')
{
float parametr = Serial.parseFloat(); // za 'y' nasleduje nejake desetinne cislo
if(parametr > 1.5) digitalWrite(11, HIGH); // pro vetsi cislo nez 1.5 se LED rozsviti
else digitalWrite(11, LOW); // pro mensi cislo LED zhasne
}
if (funkce == 'z')
{
char parametr = Serial.read(); // druhy znak je parametr '1' nebo jakykoliv jiny znak
if(parametr == '1') digitalWrite(12, HIGH); // "z1" rozsviti LED
else digitalWrite(12, LOW); // "z0" zhasne LED
}
}
}
Re: Problém s čtením dat z COM portu (sériová komunikace)
Napsal: 31 bře 2022, 19:31
od vasik006
Děkuji moc, to se bude velmi hodit, protože budu přidávat další kontrolky.
Teď ještě zjistit, jak do programu informace posílat. Zkoušle jsem Serial.print("x1") například, ale takhle to nejspíš nepůjde. Samozřejmě posílané proměnné z Arduina mám taky v programu pro komunikaci s simulátorem definované akorát v bloku "PRIJIMEJ" a ne "POSILEJ". Např. tlačítko, též se stavy 0 a 1 jsem označil písmenem x.
Pokus o kód zde:
Kód: Vybrat vše
const int buttonPin = 2;
const int ledPin = 13;
int buttonState = 0;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
Serial.begin(9600);
}
void loop() {
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH){
Serial.print("p1");
}
}
Definice proměnné:
Re: Problém s čtením dat z COM portu (sériová komunikace)
Napsal: 31 bře 2022, 19:45
od AstroMiK
Serial.print určitě půjde, ale s tím tlačítkem je to na delší diskusi a na to teď nemám.
Musí se řešit odrušení zakmitávání a detekovat hrany. Příkaz se pak do sériové linky odešle jen při hraně.