Weird digitalWrite issue

Status
Not open for further replies.

WS2812B

Member
I am currently working on a big project and currently developing some Code for a Teensy 3.2. It is supposed to communicate with several other uC but this is not my problem. To achieve the communication the Teensy 3.2 has to pulse on a pin for 10uS.

I am doing this like that:
Code:
digitalWrite(pins.INRPT_SMC_REN, HIGH);
delayMicroseconds(10);
digitalWrite(pins.INRPT_SMC_REN, LOW);

Just calling this in the loop works but when moving this code into a member function of a class and calling this function, it does not. I can clearly see this with my oscilloscope.

The whole Code: Relevant is: typedef struct PinOut{};, setupPins();, pulseInterrupt()

Code:
typedef struct PinOut
{
	uint8_t REL_SMC = 14;
	uint8_t Q_REL = 15;
	uint8_t REL = 16;
	uint8_t RST_REL = 25;
	uint8_t SET_REL = 27;
	uint8_t Q_MOS = 28;
	uint8_t SET_MOS = 32;
	uint8_t RST_MOS = 33;

	uint8_t RX1 = 0;
	uint8_t TX1 = 1;
	uint8_t RX2 = 26;
	uint8_t TX2 = 31;
	uint8_t RX3 = 7;
	uint8_t TX3 = 8;
	uint8_t INRPT_SMC_ESP = 3;
	uint8_t INRPT_ESP_SMC = 4;
	uint8_t INRPT_SMC_REN = 5;
	uint8_t INRPT_REN_SMC = 6;
	uint8_t INRPT_SMC_IO = 21;
	uint8_t INRPT_IO_SMC = 22;

	uint8_t FAN_PWM = 23;

	uint8_t I2C_SCK = 29;
	uint8_t I2C_SDA = 30;

	uint8_t T_IRQ_Disp = 2;
	uint8_t DC_Disp = 9;
	uint8_t CS_Disp = 10;
	uint8_t SDI_Disp = 11;
	uint8_t SDO_Disp = 12;
	uint8_t SCK_Disp = 13;
	uint8_t T_CS_Disp = 24;
};

#include "RenderState.h"
#include "ESP8266State.h"
#include "Protocolconstants.h"

byte myData[5] = { 1, 2, 3, 4, 5 };

PinOut pins;
ESP8266State ESP(pins);
RenderState RENDER(pins);

void ISR_ESP() {}
void ISR_REN() { RENDER.ISR(); }
void ISR_IO() {}

void initSerial()
{
	Serial.begin(9600);
	while (Serial.available())
		Serial.read();
	Serial1.begin(921600);
	while (Serial1.available())
		Serial1.read();
	Serial2.setRX(pins.RX2);
	Serial2.setTX(pins.TX2);
	Serial2.begin(921600);
	while (Serial2.available())
		Serial2.read();
	Serial3.begin(115200);
	while (Serial3.available())
		Serial3.read();
}

void setupPins() 
{
	pinMode(pins.INRPT_SMC_ESP, OUTPUT);
	digitalWrite(pins.INRPT_SMC_ESP, LOW);
	pinMode(pins.INRPT_SMC_REN, OUTPUT);
	digitalWrite(pins.INRPT_SMC_REN, LOW);
	pinMode(pins.INRPT_SMC_IO, OUTPUT);
	digitalWrite(pins.INRPT_SMC_IO, LOW);
	pinMode(pins.INRPT_ESP_SMC, INPUT);
	pinMode(pins.INRPT_REN_SMC, INPUT);
	pinMode(pins.INRPT_IO_SMC, INPUT);
	attachInterrupt(pins.INRPT_ESP_SMC, ISR_ESP, RISING);
	attachInterrupt(pins.INRPT_REN_SMC, ISR_REN, RISING);
	attachInterrupt(pins.INRPT_IO_SMC, ISR_IO, RISING);
}

void setup()
{
	delay(50);
	initSerial();
	setupPins();
	delay(1000);
}

void loop()
{
	RENDER.pulseInterrupt(); //NO Pulse
	/*
	Serial.println("Pulsing!");
		digitalWrite(pins.INRPT_SMC_REN, HIGH);
		Serial.println("High");
		delayMicroseconds(10);
		digitalWrite(pins.INRPT_SMC_REN, LOW);
		Serial.println("Low");
	*/ //Pulses successfully!
	delay(20);
}
*RenderState.h*
Code:
#ifndef RENDERSTATE_H
#define RENDERSTATE_H
#include "Protocolconstants.h"
class RenderState
{
public:
	RenderState(PinOut p) : pins(p) {}

	void pulseInterrupt()
	{
		Serial.println("Pulsing!");
		digitalWrite(pins.INRPT_SMC_REN, HIGH);
		Serial.println("High");
		delayMicroseconds(10);
		digitalWrite(pins.INRPT_SMC_REN, LOW);
		Serial.println("Low");
	}

	void transmit(byte * data) 
	{
		bool fail = false;
		int datalen = sizeof(data);
		start:
		pulseInterrupt();
		delayMicroseconds(100);
		if (!(Serial1.available() == 1)) {
			Serial.print("Serial1.available() incorrect! Expected = 1, Serial1.available() = ");
			Serial.print(Serial1.available());
			Serial.println(" ,Occured at READY response of RENDERuC. Retrying...");
			goto start;
		}
		else
		{
			if (!(Serial1.read() == READY)) {
				Serial.print("REN_READY response wrong! Retrying...");
				goto start;
			}
			else
			{
				for (int i = 0; i < datalen; i++)
					Serial1.write(data[i]);
				Serial1.flush();
				delayMicroseconds(100 + (2 * datalen));
				int n_received = Serial1.available();
				if (!(n_received == (datalen))) {
					Serial.print("Approving DATALEN failed! Expected: ");
					Serial.print(datalen);
					Serial.print(" ,Received: Serial1.available() = ");
					Serial.println(n_received);
					Serial.println(" ,Retrying...");
					Serial1.write(FAILED);
					goto start;
				}
				else
				{
					for (int i = 0; i < datalen; i++)
						if (!(Serial1.read() == data[i]))
							fail = true;
					if (fail) {
						Serial.println("Transmission failed at approving data! Retrying...");
						goto start;
					}
					else
					{
						Serial1.write(ACKNOWLEDGE);
						Serial1.flush();
						Serial.println("Transmission successfull!");
					}
				}
			}
		}
	}

	void ISR()
	{
		if (initialized) {

		}
		else
		{
			
		}
	}

	bool initialized = false;

private:
	PinOut & pins;
};
#endif

*Protocolconstants.h* irrelevant but:
Code:
#ifndef PROTOCOLCONSTANTS_H
#define PROTOCOLCONSTANTS_H

//UNIWAY
#define ACKNOWLEDGE 254

#define SLAVEINIT 253

#define READY 252

#define FAILED 251

#endif
 
I cannot comment on why you do not see the pulse, but I would suggest to use digitalWriteFast() to speedup response.
I use from time to time digitalWriteFast(pin,HIGH); digitalWriteFast(pin,LOW); and can see it easily on a 500 MS/s Logic analyzer.
 
I cannot comment on why you do not see the pulse, but I would suggest to use digitalWriteFast() to speedup response.
I use from time to time digitalWriteFast(pin,HIGH); digitalWriteFast(pin,LOW); and can see it easily on a 500 MS/s Logic analyzer.

Thank you although it did not work. I am using this pulse to interrupt another uC. I am interested in the rising edge, 10uS is very long but I think it does not really matter but don't quote me on that.
 
If it were me, I would probably assume something simple like maybe not trying to write to the same pin...

So I would probably put in something like a Serial.printf... That prints out the Pin number that you are passing into pinMode(), so you can verify that the pinMode for that pin is called.

Likewise in your pulseInterrupt function again print out the pin number you are using doing the digital Write to... That way you can verify that the actual pin is getting a write and the right function is called.

Then I would probably also put a print in the loop of again the pin number that you do the digitalWrites that work... Just to make sure they are correct...

Again in cases like this I assume I probably missed something like maybe another #define for the pin that is used in the library version versus your inline code...
 
If it were me, I would probably assume something simple like maybe not trying to write to the same pin...

So I would probably put in something like a Serial.printf... That prints out the Pin number that you are passing into pinMode(), so you can verify that the pinMode for that pin is called.

Likewise in your pulseInterrupt function again print out the pin number you are using doing the digital Write to... That way you can verify that the actual pin is getting a write and the right function is called.

Then I would probably also put a print in the loop of again the pin number that you do the digitalWrites that work... Just to make sure they are correct...

Again in cases like this I assume I probably missed something like maybe another #define for the pin that is used in the library version versus your inline code...

You solved it, Thank You!

The mistake was at the constructor of the class RenderState:
Code:
RenderState(PinOut p) : pins(p) {}
This was wrong, I wanted to define a reference of the struct PinOut called "pins" with the argument "p"
This is correct, one single character missing:
Code:
	RenderState(PinOut & p) : pins(p) {}

Due to this, the reference stayed undefined and just returned zero for everything which would have let pin 0 pulse but this pin is already used for UART.
 
You are welcome,

As my reply suggested, I have been hit way too many times with something like this... ;)
 
Status
Not open for further replies.
Back
Top