Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

digitalWrite writes after yield() or delay(0) #716

Closed
Duality4Y opened this issue Aug 22, 2015 · 4 comments
Closed

digitalWrite writes after yield() or delay(0) #716

Duality4Y opened this issue Aug 22, 2015 · 4 comments

Comments

@Duality4Y
Copy link
Contributor

Duality4Y commented Aug 22, 2015

I am having a peculiar issue,
I am trying to write a pin low and high. and notice that it doesn't take effect immediately,
my application requires it to be immediate, because it triggers a conversion (ADC) and has to be read directly after. I had scoped the output, to find the problem.

uint16_t readAnalogChannel(int channel)
{
    int adcvalue = 0;
  int b1 = 0, b2 = 0;
  int sign = 0;

  // command bits for MCP3304
  // 0000 = diff, ch0 = in+, ch1 = in-
  // 0010 = diff, ch2 = in+, ch3 = in-
  // 0100 = diff, ch4 = in+, ch5 = in-

  digitalWrite (SELPIN, LOW); // Select adc
  delay(0);

  // first byte
  // first byte will always be B000010xx where xx are the D2 and D1 channel bits  
  byte commandbits = B0000110;
  commandbits |= (channel >> 2);         // high bit of channel

  SPI.transfer(commandbits);       // send out first byte of command bits

  // second byte; Bx0000000; leftmost bit is D0 channel bit
  commandbits = B00000000;
  commandbits |= (channel << 6);        // if D0 is set it will be the leftmost bit now
  b1 = SPI.transfer(commandbits);       // send out second byte of command bits

  // hi byte will have XX0SBBBB
  // set the top 3 don't care bits so it will format nicely
  b1 |= B11100000;
  //Serial.print(b1, BIN); Serial.print(" ");
  sign = b1 & B00010000;
  int hi = b1 & B00001111;

  // read low byte
  b2 = SPI.transfer(b2);              // don't care what we send
  //Serial.print(b2, BIN); Serial.print("\r\n");
  int lo = b2;
  digitalWrite(SELPIN, HIGH); // turn off device
  delay(0);

  int reading = hi * 256 + lo;

  if (sign) {
    reading = (4096 - reading) * -1;
  }

  return (reading);
}

Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

@Links2004
Copy link
Collaborator

the maximum GPIO change frequency is limited by espressif to ~8Mhz.

but you can speed up you SPI code by using SPI.transferBytes
https://github.com/esp8266/Arduino/blob/esp8266/hardware/esp8266com/esp8266/libraries/SPI/SPI.cpp#L403

the fastest possible way to change the GPIOs is using the GPOC and GPOS register.
see here for example:
https://github.com/esp8266/Arduino/blob/esp8266/libraries/Adafruit_ILI9341/Adafruit_ILI9341.cpp#L159

@Duality4Y
Copy link
Contributor Author

I see And I understand I think, but spi clock freq is set to 10MHz.
and the point I am trying to make is that when i do a digitalWrite(pin, low) it doesn't do so "immediately",
what i meen is that the code under the digitalWrite runs before the pin is pulled low. and that is not allowed.

@sticilface
Copy link
Contributor

This might be related to the issue that Makuna had with the WS2812s. The first bit was always longer for some reason. He solved it in this commit

Makuna/NeoPixelBus@8596504

by using ICACHE_RAM_ATTR

and moving the function to a C file, as the arduino IDE seemed to ignore it if it was in a cpp file. I could most certainly be wrong though.

On 23 Aug 2015, at 13:09, Robert [email protected] wrote:

I see And I understand I think, but spi clock freq is set to 10MHz.
and the point I am trying to make is that when i do a digitalWrite(pin, low) it doesn't do so "immediately",
what i meen is that the code under the digitalWrite runs before the pin is pulled low. and that is not allowed.


Reply to this email directly or view it on GitHub #716 (comment).

@devyte
Copy link
Collaborator

devyte commented Oct 20, 2017

I think the previous comment about ICACHE_RAM_ATTR is relevant. Without it, there could be a flash access triggered, causing odd behavior and crashes. Also, for timing-sensitive code, there are other things to consider (e.g.: code for reading DHT sensors).
Not the right place to discuss this. Closing per #3655 .

@devyte devyte closed this as completed Oct 20, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants