Pages: 1 [2]   Go Down
Author Topic: Writing output values to pins back to back seems buggy, digitalwritefast() too  (Read 2167 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Jr. Member
**
Karma: 0
Posts: 82
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Long story short you guys got me riled up (aggravation is a wondrous motivator, eh?) and in getting the code ready to send in here and making a video explaining things step by step, I saw the flaw in my logic.  It was very similar to the first problem I had with the time out with millis() (this was before I wrote in for help), and I should have seen it sooner.

This is where I am at now, with much comments removed and digitalWriteFast() not in use.

Code:
#include <ServoDecode.h>
#include <digitalWriteFast.h>

char * stateStrings[] = {"NOT_SYNCHED", "ACQUIRING", "READY", "in Failsafe"};
  
// Define readable non-backwards states for relays.
// This is because relays are active LOW.  That means you can ground the pin and activate the relay.
const byte RELAY_ON = 0;
const byte RELAY_OFF = 1;

// Give each relay friendly name and map to Arduino Digital I/O pin number
const byte Relay_1 = 2;  // wire 1 of the engine kill actuator.  Pulse to allow engine to run.
const byte Relay_2 = 3;  // wire 2 of the engine kill actuator.  Pulse to kill engine.
const byte Relay_3 = 4;  // brake controller
const byte Relay_4 = 5;  // currently unused

const unsigned long idleMotorKill = 5000; // delay to kill the motor
long whatTimeIsIt = 0;
boolean timeOut = false;

void setup(){
  
  //ServoDecode setup
  ServoDecode.begin();
  ServoDecode.setFailsafe(3,1234); // set channel 3 failsafe pulse  width
  
  // Relay Setup Initialize Pins so relays are inactive at reset
  digitalWrite(Relay_1, RELAY_OFF);
  digitalWrite(Relay_2, RELAY_OFF);
  digitalWrite(Relay_3, RELAY_OFF);
  digitalWrite(Relay_4, RELAY_OFF);
  
  // THEN set pins as outputs
  pinMode(Relay_1, OUTPUT);  
  pinMode(Relay_2, OUTPUT);  
  pinMode(Relay_3, OUTPUT);  
  pinMode(Relay_4, OUTPUT);    
  delay(1000); // Check that all relays are inactive at Reset
  
  // Prevent motor from starting and engage breaks
  engineKill();
  brakesEngage();

} // end setup()


void loop(){

  if(ServoDecode.getState()!= READY_state) { // transmitter is off or out of range
    engineKill(); // kill motor
    brakesEngage(); // engage brakes
    whatTimeIsIt = 0; // used as a semaphore
    timeOut = false; // resets this semaphore
  } // end if() transmitter not ready
  
  if(ServoDecode.getState()== READY_state) {
    if(whatTimeIsIt==0){ // tests for if it's the first loop through of the ready state
      whatTimeIsIt = millis(); // if it's the first loop through, make a note of the time
    } // end if() testing for first loop through
    
    if(!timeOut){
      engineAllow(); // allow motor to be cranked
      brakesDisengage(); //disengage brakes
    } // if the transmitter has not timed out

    if (millis() > (whatTimeIsIt + idleMotorKill) ){ // if 5 seconds has passed since entering the ready state, kill the motor and engage the brakes
      engineKill();
      brakesEngage();
      timeOut = true;
    } // end test for timeOut
  } // end if() transmitter ready
  
} // end main loop()

void engineKill(){
  digitalWrite(Relay_1, RELAY_OFF); // just in case it was on for some random reason; prevents frying relays and/or actuators
  digitalWrite(Relay_2, RELAY_ON); // eventually pulse it, but for now just latch it
} // end engineKill

void engineAllow(){
  digitalWrite(Relay_2, RELAY_OFF); // just in case it was on for some random reason; prevents frying relays and/or actuators
  digitalWrite(Relay_1, RELAY_ON); // eventually pulse it, but for now just latch it
} // end instantEngineKill

void brakesEngage(){
  digitalWrite(Relay_3, RELAY_ON); // engages the brakes by closing the circuit to power them
} // end brakesEngage

void brakesDisengage(){
  digitalWrite(Relay_3, RELAY_OFF); // disengages the brakes by opening the circuit
} // end brakesDisengage


Notice the new boolean timeOut semaphore and additional conditional logic [ if(!timeOut){} ]within the loop; that's what I was missing.  As for everyone who was asking about code, the whole thing was in the OP this whole time.  Yes I was running the same code as in the OP when I shot the first video.  Sorry about the lack of audio, I was at work trying to be discreet about it and it seemed self evident of what I was doing based on the code.

Video is uploading now from my phone, it'll be in my channel.  You can get an idea of what I am trying to do as I do explain the process of what I want to happen. It's taking it's sweet time uploading, so I'll edit this post after the fact with a direct link to it.  I tried to talk slow, but my phone has audio/video sync issues of about a fraction of a second; enough to be annoying.

Direct link to the video:
https://www.youtube.com/watch?v=uoMIJJe4iQU&list=UUaSw8RHFCs8l8BJgwOVaySQ&index=1&feature=plcp
« Last Edit: July 31, 2012, 08:53:55 pm by allanonmage » Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 82
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

PaulS was just saying, in a rather humorous way IMHO, that wanting to do things "fast" and combining that with serial comms, is a contradiction in requirements.
It's like saying you want to organize a fast turtle race.

Ah that makes sense now. I'm not sure how clear I was in that other thread and this one, but I'm not familiar with microcontrollers; I typically work with/on PCs, or in the case of my job, a completely proprietary system with proprietary software.  What I'm getting at is my implicit communication skills in this world are going to be a while in developing.  Kind of like how sarcasm is lost on young children.  I do try to do some research and/or trial & error before I ask questions though.

Quote from: Nick Gammon
Stop right there. First, your code is wrong in about 5 points. If you are going to say code X doesn't work, post code X, and prove it. Missing semicolons, "high" instead of "HIGH", incorrect capitalization of digitalWrite and so on.
So you are saying this code:

Code:
digitalWrite(2, HIGH);
digitalWrite(3, LOW);

Does not turn pin 2 high and pin 3 low?

No, my point was, and up till I just figured out my logic error, always was, that the *second line*, ie "digitalWrite(3, LOW);" was not executing.  In this case it just appeared to not be executing when it actuality it was; without proper conditional logic another function was just writing all over it and it was looping fast enough that it appeared to not work.  The dim LED was somewhat of a clue, albeit it too faint for me to pick up on.

Quote from: Nick Gammon
So stop trying to use digitalWriteFast

Is it not a good idea to use this library?  Or does this fall under the fact that if it doesn't work normally it won't work optimized?

Have you set the pins to outputs? First important point. If not, we can skip the rest.
In fact, post your whole code, not just snippets, because that hides whatever-it-is you are doing that causes the problem that you perceive.

I'm not trying to be rude, but I'm going to be blunt here: it's in the OP. In a code block labeled "Here's the test code I'm working on:"


Quote from: Nick Gammon
Quote
If you or someone else would be so kind as to confirm if activating digitalwrite()'s on sequential pins is *supposed* to work, I would much appreciate it.

Do you seriously think Atmel would sell any chips if you could not turn on or off two things in a row reliably? Of course it is supposed to work.

When I'm new to a piece of tech and it's not working the way I want, I try removing unsubstantiated assumptions, guesses, or things I "think" I know.  As not having a clue, I could only assume that was the case, as I had little to no proof it was one way or another.  In fact, I even went so far as to postulate something halfway plausible as to why it might not work the way I originally thought it would.  

Someone once said that you can't actually debug your own code because if you're not capable enough to see the problem, you can't see it.  Or something like that.  It was smart & deep.  Anyways, I thought I had double and triple checked my code at that point, which is why I started to wonder about other things.

I know microcontrollers are more limited than PCs in some aspects, but I don't quite understand the hows and whys and limits of that concept, so I looked around, came up with a guess, and asked if I was close or way off.  Seems that this time I was way off.  That's what I meant by:

Quote
I'm not sure if I did something stupid, or just didn't take into account the nature of the architecture.

In this case it was the former.  For reference, my first foray into my company's language landed me in the latter.
« Last Edit: July 31, 2012, 09:01:34 pm by allanonmage » Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 98
Posts: 4802
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Someone once said that you can't actually debug your own code because if you're not capable enough to see the problem, you can't see it. 

Not always true in more than one way.

You may be tired and need some rest.

or

You may be fixated and need to take a clean view, which is very common, very left-brain.

OTOH your original idea may be flawed and then it's up to you to find that out.
Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 480
Posts: 18732
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

 In this case it just appeared to not be executing when it actuality it was; without proper conditional logic another function was just writing all over it and it was looping fast enough that it appeared to not work.  The dim LED was somewhat of a clue, albeit it too faint for me to pick up on.

Yes, that can happen. If possible, use a logic analyzer or oscilloscope to check whether an output is on all the time or switching on and off rapidly.


Is it not a good idea to use this library?  Or does this fall under the fact that if it doesn't work normally it won't work optimized?

I'm suggesting that you were flying off on a tangent here. The problem was not with digitalWrite.

I'm not trying to be rude, but I'm going to be blunt here: it's in the OP. In a code block labeled "Here's the test code I'm working on:"

Sorry. I acknowledged that in my next post.

Someone once said that you can't actually debug your own code because if you're not capable enough to see the problem, you can't see it.  Or something like that.  It was smart & deep.  Anyways, I thought I had double and triple checked my code at that point, which is why I started to wonder about other things.

I understand, but it would have been good to make a test case with a half-dozen lines of code that simply turned pins on and off in quick succession. That would prove/disprove your theory about timing. Once you establish that the processor can, in fact, turn pins on and off quickly you might have looked more closely at the surrounding logic.
Logged


0
Offline Offline
Full Member
***
Karma: 2
Posts: 156
It was all digital
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi allanonmage

I don't need a video - just explane in simple words what you want to achive with your program.

I have looked at your program and this is how I interpretate it:

1) Waite for ServoDecode to give READY_state.
2) If READY_state: Set relays to running state.
3) If !READY_state: Set realys to not running state, and prepare for a new run.
4) If running state has been activitated for too long: Set relays to not running state and do nothing forever.

Is this correct?

-Fletcher
Logged

New Hampshire
Offline Offline
God Member
*****
Karma: 17
Posts: 781
There are 10 kinds of people, those who know binary, and those who don't.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi allanonmage

I don't need a video - just explane in simple words what you want to achive with your program.

I have looked at your program and this is how I interpretate it:

1) Waite for ServoDecode to give READY_state.
2) If READY_state: Set relays to running state.
3) If !READY_state: Set realys to not running state, and prepare for a new run.
4) If running state has been activitated for too long: Set relays to not running state and do nothing forever.

Is this correct?

-Fletcher


I think you missed a few posts.  He found the source of his problem himself.
Logged


NZ
Offline Offline
Jr. Member
**
Karma: 1
Posts: 91
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Don't forget when you're debugging you can insert a sizeable delay after each output to see if anything is happening or use LED 13 as an indicator that you got to "here" in the code.
It is one of the benefits of delay(), it stops everything (unless you are using a time slicing OS).

// ie
digitalWrite(2, HIGH);
delay(1000);
digitalWrite(3, LOW);
delay(1000);
// etc

k
Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 98
Posts: 4802
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I wouldn't worry about OS on an Arduino.
Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Pages: 1 [2]   Go Up
Jump to: