Nefunkční PinMode(x,OUTPUT)

Wiring, C++, C, Java, ...
Pravidla fóra
Toto subfórum slouží k řešení obecných otázek kolem programování (konstrukce, knihovny, alokace paměti, ...)
Odpovědět
PetrB
Příspěvky: 141
Registrován: 20 čer 2018, 13:39
Reputation: 0

Nefunkční PinMode(x,OUTPUT)

Příspěvek od PetrB » 10 úno 2023, 11:12

Ahoj,
mám program pro Arduino Nano, kde se snažím nastavit některé piny na output. Konkrétně 4,5 a 8. Osmička se mi daří, ale 4 a 5 zůstávají stále vstupní a nevím proč.

Mám následující kód (v vSeznam je, které piny se nastavují v getBite na jakou hodnotu)

Kód: Vybrat vše

	for (int i = 0; i < cPinCount; i++) {
		if (vSeznam.getBite(i)) {
#ifdef EEPROM_Dump
			Serial.print(F("Nastavuji PIN="));
			Serial.print(i + 1);
			Serial.print('=');
			Serial.print(getPinMode(i + 1));    //Pozice v zápisu je od nuly, ale piny jsou od jedničky
			Serial.print(':');
#endif
			pinMode(i + 1, OUTPUT);
#ifdef EEPROM_Dump
			Serial.println(getPinMode(i + 1));
#endif
			if (getBite(i)) {
				digitalWrite(i + 1, HIGH);
			}
			else {
				digitalWrite(i + 1, LOW);
			}
		}
	}
Takto zjišťuji mód na konkrétním portu

Kód: Vybrat vše

#define UNKNOWN_PIN 1024

uint8_t getPinMode(uint8_t pin)
{
	uint8_t bit = digitalPinToBitMask(pin);
	uint8_t port = digitalPinToPort(pin);

	// I don't see an option for mega to return this, but whatever...
	if (NOT_A_PIN == port) return UNKNOWN_PIN;

	// Is there a bit we can check?
	if (0 == bit) return UNKNOWN_PIN;

	// Is there only a single bit set?
	if ((bit & bit) - 1) return UNKNOWN_PIN;

	volatile uint8_t* reg, * out;
	reg = portModeRegister(port);
	out = portOutputRegister(port);

	if (*reg & bit)
		return OUTPUT;
	else if (*out & bit)
		return INPUT_PULLUP;
	else
		return INPUT;
}
Po proběhnutí rutiny mám v logu uvedeno toto:
Piny pred nastavenim:
0 i i i i i i i i
1 i i i i i i
Nastavuji PIN=4=0:0 //to znamená, že pin 4 se nastavil z Input na Input
Nastavuji PIN=5=0:0
Nastavuji PIN=8=0:1 //to znamená, že pin 8 se nastavil z Input na output (stav zjištěný před pinMode a po pinMode)
Piny nastaveny
0 i i i I I i i O
1 i i i i i i
malé i znamená, že pin je vstupní a je na něm 0
velké I znamená, že pin je vstupní a je na něm 1
malé o by znamenale, že pin je výstupní a je na něm 0
velké O znamená, že pin je výstupní a je na něm 1

Z toho výpisu je vidět, že i 4 a 5 se nastavil, ale pouze jako vstupní a je na nich jednička. Osmička se nastavila jako výstupní a je tam jedna.

K arduinu nemám nic připojené a tohle je jediné místo, kde ten pinMode nastavuji.
Hledal jsem, jestli třeby tyto piny nejsouo pro něco systémově rezervované, ale nic jsem nenašel.
Nevíte, čím by to mohlo být nebo co dělám špatně?

Díky

Pb

ondraN
Příspěvky: 932
Registrován: 08 srp 2019, 20:01
Reputation: 0

Re: Nefunkční PinMode(x,OUTPUT)

Příspěvek od ondraN » 10 úno 2023, 11:38

A proč nepoužiješ
pinMode(4,OUTPUT);
a pak neotestuješ krátkým kódem, který bude měnit stav pinu po pár vteřinách a měřákem nebo LEDkou uvidíš, jestli to funguje.

PetrB
Příspěvky: 141
Registrován: 20 čer 2018, 13:39
Reputation: 0

Re: Nefunkční PinMode(x,OUTPUT)

Příspěvek od PetrB » 10 úno 2023, 12:07

To by byla druhá fáze (test hw). Teď mne spíše zajímalo, jestli nedělám něco blbě.

PetrB
Příspěvky: 141
Registrován: 20 čer 2018, 13:39
Reputation: 0

Re: Nefunkční PinMode(x,OUTPUT)

Příspěvek od PetrB » 10 úno 2023, 12:20

Hm, tak bych spíše tipoval chybu v té rutině getPinMode (staženo z netu), protože jsem udělal pinMode(x,OUTPUT) pro 1..10 a v podstatě to píše změny jenom u 8. pinu.

ondraN
Příspěvky: 932
Registrován: 08 srp 2019, 20:01
Reputation: 0

Re: Nefunkční PinMode(x,OUTPUT)

Příspěvek od ondraN » 10 úno 2023, 13:59

Chyba bude nejspíš v získání adresy registru GPIO portu nebo interpretace bitů nastavení. Pokud bys to chtěl řešit přes něj (registr), musíš se podívat přímo na ten MCU co je na arduinu a pak do katalogového listu a najít si ty adresy a význam jednotlivých bitů.

PetrB
Příspěvky: 141
Registrován: 20 čer 2018, 13:39
Reputation: 0

Re: Nefunkční PinMode(x,OUTPUT)

Příspěvek od PetrB » 10 úno 2023, 15:43

tak HW funguje. Dioda poslušně bliká. Našel jsem na nějaké jiné stránce, kde je také ten kód pro getPinMode, že to je pro ATMEGA168/ATMEGA328. Kdežto Nano je na 328p, což může být rozdíl.

PetrB
Příspěvky: 141
Registrován: 20 čer 2018, 13:39
Reputation: 0

Re: Nefunkční PinMode(x,OUTPUT)

Příspěvek od PetrB » 10 úno 2023, 23:52

Tak jsem to odhalil. Byla to vyloženě programová chyba.

Kód: Vybrat vše

uint8_t getPinMode(uint8_t pin)
{
	uint8_t bit = digitalPinToBitMask(pin);
	uint8_t port = digitalPinToPort(pin);
	
	// I don't see an option for mega to return this, but whatever...
	if (NOT_A_PIN == port) {
		return UNKNOWN_PIN;
	}

	// Is there a bit we can check?
	if (0 == bit) {
		return UNKNOWN_PIN;
	}
/* na Nano to nefunguje, kromě bitu 8 to všechno končilo s UNKNOWN_PIN
	// Is there only a single bit set?
	if ((bit & bit) - 1) {
		Serial.println(F("NOT_2BIT"));
		return UNKNOWN_PIN;
	}
*/
	volatile uint8_t* reg, * out;
	reg = portModeRegister(port);
	out = portOutputRegister(port);

	if (*reg & bit)
		return OUTPUT;
	else if (*out & bit)
		return INPUT_PULLUP;
	else
		return INPUT;
}
Tu pochybnou část kódu jsem odkomentoval.

druhá chyba byla zde:

Kód: Vybrat vše

void tPinRec::pinDump()
{
	byte radek = 0;
	char co = ' ';
	bool NL = false;
	uint8_t gPM;  //to tady původně nebylo

	for (byte i = 1; i <= cPinCount; i++) {
		if (NL) {
			Serial.println();
			NL = false;
		}
		if (i % 8 == 1) Serial.print(radek);
		Serial.print(' ');
		/********doplněno******/
		gPM = getPinMode(i);   //původně zde bylo pouze switch(getPinMode(i)) a tomu se zjevně nelíbil výsledek v podobě UNKNOWN_PIN,který
		switch (gPM) {             //špatně interpretoval (asi vzal jenom dolní byte) jako INPUT a tím to psalo nesmysly. Použití proměnné gPM   
		/*******************/       //pomohlo
		case UNKNOWN_PIN:
			co = '?';
			break;
		case INPUT: 
			co = 'I';
			break;
		case OUTPUT:
			co = 'O';
			break;
		case INPUT_PULLUP:
			co = 'P';
			break;
		default:
			co = '!';
			Serial.println();
			Serial.println(getPinMode(i));
			break;
		}
		if (digitalRead(i) == LOW) co = tolower(co);
		Serial.print(co);
		if (i % 8 == 0) {
			NL = true;
			radek++;
		}
	}
	if (!NL) Serial.println();
}
Tenhle nový kód funguje spolehlivě a dle očekávání.
Díky za konzultaci.

Pb

Odpovědět

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 12 hostů