I am trying to toggle a pin on and off 16 times in short bursts because my project requires to determine on which edge another pin reads a transition from low to high.
Toggling the pin with a for loop and delay(); is simple enough, it gives me all the control about the delay between rising and falling edges that I need to make precise and consistent readings.
But it also slow everything else down, so much that it's kind of useless in conjunction with pretty much everything else.
I have tried to figure out a way of strobing the pin with the method in the BlinkWithoutDelay-example, but I can't figure out how to control the delay between the edges. Actually, I couldn't even figure out how to use a for loop to toggle the pin 16 times that way. The loop just exits on every toggle.
Am I missing something obvious here or am I trying the wrong method in the first place?
Could someone please point me in the right direction?
Could you post the code you have? Please use code tags (the "</> icon on the button bar).
And please explain more about the timing you need. The pin needs to go on and off 16 times - do you mean "on, off" is one time and you need that 15 times more? Do the 16 changes make up the "short burst"? How long between each transition? How long between the bursts?
What you are describing is bit banging. But can't you just use a PWM pin? That shouldn't effect performance, and you can alter the PWM frequency further by messing aroudn with the clock prescaler.
Maybe, if i've understand the question, you can put the toggling on a if statement where you compare the value of a var until it's >= to 0 and for each loop you decrease the var, initialized to 15 and your sketch will toggle you pin for 16 times.
const int ledPin = 13; // the number of the LED pin
int ledState = LOW; // ledState used to set the LED
unsigned long previousMillis = 0; // will store last time LED was updated
// constants won't change :
const long interval = 1000; // interval at which to blink (milliseconds)
void setup() {
// set the digital pin as output:
pinMode(ledPin, OUTPUT);
}
void loop()
{
for (int i = 0; i < 15; i++) {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa:
if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;
// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState);
}
}
}
Thanks for the details, MontySylver. They are making things clearer.
immediately read the other pin for 10 times to avoid false readings
do some error correction
I should have asked earlier, is this an analog or digital input?
Overall, to summarise, you want to generate 16 cycles of a square wave (1800us high, 1800us low). After each of the 16 low to high transitions, you check if your input is a valid high. The result is the cycle number on which the input goes valid high. Is that correct?
I should have asked earlier, is this an analog or digital input?
It's a digital input.
Overall, to summarise, you want to generate 16 cycles of a square wave (1800us high, 1800us low). After each of the 16 low to high transitions, you check if your input is a valid high. The result is the cycle number on which the input goes valid high. Is that correct?
That is the exact technical description of what I am trying to accomplish! I am not good at explaining things in technical terms...
As for an explanation what that code is supposed to do: I started to write code for TTP229 capcitive touchpads months ago and want to have something that is usable in a practical situation instead of a "good enough" proof of concept.
Try using this code as a starting point. You need to set correct pin numbers and, obviously, add your code for reading the input pin and deciding if it is a valid high
Make sure that the code you add is non-blocking and executes quickly enough to allow the 1800us timeout to run "on time" to give you the correct period of the output toggle.
#define HALF_PERIOD 1800UL // duration of high or low in microseconds
#define TEST_LIMIT 15
#define OUTPUT_PIN 13 // set to your value
#define INPUT_PIN 12 // set to your value
int resultCycle;
boolean testRunning;
int outputState;
void setup()
{
Serial.begin(115200);
pinMode(OUTPUT_PIN, OUTPUT);
digitalWrite(OUTPUT_PIN, LOW);
outputState = LOW;
pinMode(INPUT_PIN, INPUT); // set INPUT or INPUT_PULLUP
resultCycle = -1; // valid result will be 0 .. 15, -1 will indicate no valid input received within TEST_LIMIT + 1 cycles
testRunning = true;
}
void loop()
{
static unsigned long lastToggle = 0;
if (testRunning)
{
unsigned long currentMicros = micros();
if (currentMicros - lastToggle >= HALF_PERIOD)
{
lastToggle = currentMicros;
if (outputState == LOW)
{
outputState = HIGH;
digitalWrite(OUTPUT_PIN, outputState);
resultCycle++; // resultCycle will be 0 on first low to high toggle
// add your code to read input
// add your code to error correct
if (/*add your expression to test for valid result*/)
{
testRunning = false; // stop test with resultCycle holding valid cycle number
}
}
else // outputState == HIGH
{
outputState = LOW;
digitalWrite(OUTPUT_PIN, outputState);
if (resultCycle == TEST_LIMIT)
{
testRunning = false; // stop test
resultCycle = -1;
}
}
}
}
else // test has finished
{
Serial.print("resultCycle = ");
Serial.println(resultCycle);
while (1); // halt
}
}
It's working (jittery) with my proof of concept code, as it did before.
Here's the code:
int confirmations = 0;
int current = 0;
boolean sdoValue;
do{
for(int i = 0; i < 17; i++){
CLR(PORTD,2);
delayMicroseconds(10);
sdoValue = digitalRead(sdoPin);
if(sdoValue == 1){
current = i;
}
SET(PORTD,2);
delayMicroseconds(10);
}
confirmations++;
delayMicroseconds(1750);
}while(confirmations <=20);
if(confirmations >=21){
return current;
confirmations = 0;
}
}
The code is completely botched together just to make it work somehow. Complete trial and error and barely reliable. Using direct port manipulation to speed things up a bit.
Here is the output on my scope. CH1 is the clock, CH2 is data.
As you can see, data goes high on a rising edge that corresponds with the number touched on the touchpad, in this case 9 (Also, the timing is horribly off). So yeah, it's dead simple and I still can't figure out how to do it properly though.