raspberry pi 2 B+ and node.js -- a drift and need a life perserver

139 views
Skip to first unread message

jps birdzbeez

unread,
Aug 18, 2015, 11:49:40 AM8/18/15
to nodejs
I am not a programmer and never claimed to be one.. I just read and read and read.. trying to learn and understand.. but for some reason I am not sure I am understanding how this works...  if someone doesn't mind I need help to point me in the correct direction to get my project going.. What I am able to do is make it work in python but I like the idea of node.js over python.. 


The project is to use my raspberry pi to raise or lower a door (not a garage door). At the top and bottom are Hall Effect sensors. Before raising the door I want to verify the door is closed. If it is closed then raise the door till it reaches the opendoor state. I have not had any luck with node.js programming..  this is what I have come up with so far..

var gpio = require('rpi-gpio');
var doorclosed = 31; //hall effect sensor when door is closed
var dooropen = 33; //hall effect sensor when door is open
var opendoor = 35; //cause door to open
var closedoor = 37; //cause door to close


function raisedoor(callback) {
  //verifydoorclosed(function verified door closed on gpio 31)
  gpio.read(doorclosed, gpio.DIR_IN, readInput);
  //if doorclosed is = true then opendoor till dooropen is true
    if dooclosed = true
    gpio.write(opendoor, 1, function(err){
      gpio.read(dooropen, true, function(err){
        gpio.write(opendoor, 0, function(err){
          callback();
        });
      });
    });
  }

I don't mind reading if someone has a link that explains what I am missing.. thank you

Ryan Schmidt

unread,
Aug 19, 2015, 5:28:41 PM8/19/15
to nod...@googlegroups.com
You said the code doesn't work, but what actually happens when you run the code?

There's one typo, at least: "dooclosed" should be "doorclosed".

"if doorclosed = true" isn't valid JavaScript. You would need to have parentheses around the condition. Also, "=" is assignment; you want "==" which is equality comparison: "if (doorclosed == true)"

I've never used GPIO before, but I took a look at the documentation:

https://www.npmjs.com/package/rpi-gpio

And what you've written doesn't seem to correspond to that API. For example, it says you must use gpio.setup before reading or writing, and the code you've shown doesn't do that.

The first time you call gpio.read, you're calling it as if it is a synchronous function, but the documentation shows an asynchronous function (i.e. one that takes a callback). It also only takes two parameters: a channel and a callback, but you're passing three parameters.

In your other call to gpio.read, you're passing three parameters again, where only two are expected, and the callback you're passing only has an error parameter, whereas the API expects to provide the value that was read as the second parameter in the callback.

Your code is also never checking or doing anything with the error parameter. You always have to check if an error occurred, and if so, do something appropriate.

Knowing, as I said, nothing about GPIO, I'm just guessing here, but as a starting point, if you wanted to check if the door is closed, it seems like the code would be:


function raisedoor(callback) {
gpio.setup(doorclosed, gpio.DIR_IN, function (err) {
if (err) return callback(err);
gpio.read(doorclosed, function (err, value) {
if (err) return callback(err);
if (value) {
// the door is closed
} else {
// the door is not closed
}
callback();
})
})
})


Probably the setup code should not actually be in the raisedoor function, but instead in an initialization function you call once at the beginning of your program.

You said you want to raise the door until it reaches opendoor state, but your code doesn't contain any loops that would be necessary for implementing "until" logic. Of course, you shouldn't actually write such loops in node since that would block the event loop. Instead you'll probably need to check the sensor, and if it is not yet the right value, use setTimeout to wait a number of milliseconds and then check again. Or, better yet, it looks like the API sends "change" events when a value has changed, so instead, you should listen for that event.

The similarity of the names of your variables (dooropen, opendoor) is confusing.

Zlatko

unread,
Aug 19, 2015, 5:28:41 PM8/19/15
to nodejs
Your code doesn't seem correct (nevermind the syntax errors). You also didn't post any potential results.

These kinds of questions would be better off at stackoverflow.com, but here are a few pointers.

The thing to realize here is that gpio.read and gpio.write are async functions, and your first call gpio.read(doorclosed, gpio.DIR_IN, readInput); seems synchronous, so our check (if (doorclosed === true){} ) will always fail.

You also seem to have too many params (according to documentation at https://www.npmjs.com/package/rpi-gpio) at further gpio.read calls, you only need PIN number and callback. The second thing is that your second check (whether the door is closed) should most likely be polling, say, every second or so, because this way it'll make a check right away after starting the doorOpen, and it'll probably be too fast..

An example of a raiseDoor function would be as:

function raiseDoor() {

  // first check that the door is closed.
  // the callback we pass in is a function which will receive (err, value) arguments - err if there was a problem during this call, value if not.
  gpio.read(DOORCLOSED, doorClosedCallback);
}

Two things - I wrote the doorclosed in CAPS, to signal the developer (be it yourself or somebody else) that the this variable is constant, we don't plan to change it. I suggest doing this for gpio-pin numbers for code clarity.
Second thing, now we need to write this doorClosedCallback. It will be called when that gpio.read above reads the sensor value.

function doorClosedCallback (err, value) {
  // check for errors
  if (err) {
      console.log('Error checking if the door was open', err);
      return;
  }
  // if no errors, we can see the door position.
  if (value === true) {
    // door is open, skip.
    console.log('Door open, ending.');
    return;
  } else {
    // door is not open. We need to do two things:
    // 1. kick off the door motor (write to 'opendoor' PIN)
    // 2. start polling - check every second if the door is now closed, and when it is, stop the door motor.
    gpio.write(OPENDOOR, true, doorInMotion);
  }

As you can see, I'm writing true, and again offloading this check of the work complete to another function - that way it's easier to reason about those simple functions with simplified jobs.

So let's write it:

function doorInMotion (err) {
  // it will only receive an error if our gpio.write(OPENDOOR) failed - meaning, if we failed to start the door motor.
  if (err) {
    console.log('Door start failed.', err);
    return;
  }
  // now is the trick. We want to check every second if the door is open. If yes, write a zero to opendoor pin, so that we stop the engine.
  // we do this every second, and we save this interval.

  var interval = setInterval(function() { // this inner function runs every second, until somebody calls the interval.cancel();

    // every second, check the door sensor.
    gpio.read(DOOROPEN, function(err, value) {
      if (err) {
        console.log('Error reading door-open value.', err);
        return; // also could be a good idea to stop the engine here, because due to error, we don't know if the door is open or not, maybe sensor has failed.
      }
      // anyway, if the sensor didn't fail, we can check the DOOROPEN pin value:
      if (value !== true) {
        console.log('Door not yet open, keep the motor running.');
      } else {
        console.log('Door is finally open.');
        // now stop the door
        gpio.write(OPENDOOR, false, function(err) {
           if (err) {console.log('Error stopping the door motor.', err);
        });
      } 
    });
  }, 1000);
}


This is just one, basic solution example, it can probably be made better and simpler. But I think it should at least get you started.

Zlatko

unread,
Aug 19, 2015, 8:08:58 PM8/19/15
to nodejs
Forgot the interval.cancel():


On Wednesday, August 19, 2015 at 11:28:41 PM UTC+2, Zlatko wrote:

So let's write it:

function doorInMotion (err) {
  // now is the trick. We want to check every second if the door is open. If yes, write a zero to opendoor pin, so that we stop the engine.
  // we do this every second, and we save this interval.

  var interval = setInterval(function() { // this inner function runs every second, until somebody calls the interval.cancel();

    // every second, check the door sensor.
    gpio.read(DOOROPEN, function(err, value) {
      if (err) {
        console.log('Error reading door-open value.', err);
        return; // also could be a good idea to stop the engine here, because due to error, we don't know if the door is open or not, maybe sensor has failed.
      }
      // anyway, if the sensor didn't fail, we can check the DOOROPEN pin value:
      if (value !== true) {
        console.log('Door not yet open, keep the motor running.');
      } else {
        console.log('Door is finally open.');
        // now stop the door

And stop the interval here too: clearInterval(interval);

jps birdzbeez

unread,
Feb 11, 2016, 1:15:16 PM2/11/16
to nodejs
First I want to say thank you for posting this.. and secondly I want to say sorry for not replying back to you so late.  I have been tied up with another project, bathroom renovation, which has kept me frustrated.  Anyways, I have come to understand javascript and node callback functions much better. Still learning though and your code example has helped me so much.  It isn't working yet but I am sure I will get the bugs figured out with some time.  Once I do I will post back.. can't say thank you enough for the example.. helped my lightbulb in my brain go on.
Reply all
Reply to author
Forward
0 new messages