Open rodolphonetto opened 3 years ago
When we get a value back for a pin, it's going to run all the query callbacks without any regard to other pins.
There are some atypical things here that make me think this code was architected as though it were going to be written in Arduino C whereas it could be more simple
You have a digital input and a digital output. This might be a button and an LED. The "J5 way" to do this would be:
const five = require("johnny-five");
const board = new five.Board();
board.on("ready", function() {
const button = new five.Button(5);
const led = new five.Led(4);
button.on("down", function() {
led.on();
});
button.on("up", function() {
led.off();
});
});
Since the order of the callback execution is important to you, I suspect you are trying to do something more complicated. Can I ask what kind of hardware you are trying to control?
Hi, thanks for you help. I did this example before and all worked fine. The hardware I'm creating is a magnetic chessboard. I will use 64 reed switchs for it. For now I'm doing a 2x2 only for tests and I could make it work today using all kind of workarounds, of course the code is terrible but... works. There is other ideas to not use this callback hell and setTimeOuts I used? here goes the code
const five = require('johnny-five')
const board = new five.Board({ timeout: 3600 })
const a = [
{ casa: 1, status: false },
{ casa: 2, status: false },
]
const b = [
{ casa: 1, status: false },
{ casa: 2, status: false },
]
board.on('ready', function () {
const colunaA = new five.Pin({
pin: 2,
type: 'digital',
mode: 0,
})
const colunaB = new five.Pin({
pin: 3,
type: 'digital',
mode: 0,
})
const linha1 = new five.Pin({
pin: 4,
type: 'digital',
mode: 0,
})
const linha2 = new five.Pin({
pin: 5,
type: 'digital',
mode: 0,
})
board.digitalWrite(2, 1)
board.digitalWrite(3, 1)
const managePins = (time, linha, i) => {
board.wait(time, () => {
linhas.forEach((linhaDesligar) => {
if (linha !== linhaDesligar) {
board.wait(time + 30, () => {
board.pinMode(linhaDesligar, 0)
board.wait(time + 60, () => {
board.pinMode(linha, 1)
board.digitalWrite(linha, 0)
board.wait(time + 90, () => {
colunaA.query(function (state) {
a[i].status = !state.value ? true : false
})
colunaB.query(function (state) {
b[i].status = !state.value ? true : false
})
})
})
})
}
})
})
}
const linhas = [4, 5]
let time = 0
setInterval(() => {
for (let i = 0; i < linhas.length; ++i) {
;(function (i) {
setTimeout(function () {
if (i === 0) {
time = 0
}
managePins(time, linhas[i], i)
}, 200 * (i + 1))
})(i)
}
setTimeout(() => {
console.log('a1', a[0].status ? 'Tem peça' : 'Não tem peça')
console.log('a2', a[1].status ? 'Tem peça' : 'Não tem peça')
console.log('b1', b[0].status ? 'Tem peça' : 'Não tem peça')
console.log('b2', b[1].status ? 'Tem peça' : 'Não tem peça')
console.log('----------------------------------------')
}, 450);
}, 1000)
})
There's a lot of ways to do this. I'd probably start with something like:
let inHand = {}, squares = {};
let board = new five.board();
class Square {
#state = {};
constructor(config = {})) {
#state = config;
this.switch = new five.Switch(config.pin);
this.name = config.name;
this.switch.on("close", () => {
this.place();
}
this.switch.on("open", () => {
this.lift();
}
}
place() {
if (inHand) {
#state = {...inHand};
#inHand = null;
console.log(`The ${#state.color} ${#state.piece} is on square ${this.name}`);
}
}
lift() {
if (#state) {
inHand = {...#state};
#state = null;
console.log(`The ${inHand.color} ${inHand.piece} is in hand`);
}
}
}
board.on("ready", function() {
// An array of all the squares with their algebraic notation name, pin the reed switch is attached to, and their initial state
[
{ color: "white", piece: "queen", name: "a1", pin: 0 },
{ name: "b1", pin: 1 },
{ color: "black", piece: "queen", name: "a2", pin: 2 },
{ name: "b2", pin: 3 }
].forEach(config => {
squares[config.name] = new Square(config);
})
});
Idk how to thank you for such an amazing answer!
I'm studing it and trying to understand. I have two questions
What does that # means? I`ve never seen this on JS
And I dont have a pin for each switch, I use only 8 pins for collumns and 8 for rows, then I cross then to see if is on or off
and again thank you for your help!!
#
indicates a private instance field. It probably doesn't need to be private. I just used it out of habit.
then I cross then to see if is on or off
I see how that would work for one piece, but not more than one piece. I'd like to learn. Do you have a link that explains it?
Update: I found a link. I see you'll need to create a custom read loop, and I also understand now why you needed to change pin modes. Let me see if I can find where someone has done this before in J5.
I'm trying to do what is explained here: https://arduino.stackexchange.com/questions/31885/need-help-in-circuit-diagram-of-88-reed-switch-matrix
The response that has the arduino pic.
Since I'm noob with eletronics that was the best way I found out.
And again thank you so much for your help!! I'm into this problem for about 15 days, today I could solve it with that terrible soluction but of couse if we can go with a better approch would be good :D
Cool, that helps a lot. Some tips:
once
instead of on
when listening for events. Once you get an update then you can switch pin modes to move to the next columnLinha
class with an async read method. Instantiate those into an array. You can then use an asyncForEach on your array of 8 linhas. Here's an asynForEach method you can use (bonus, there is an async "waitFor" method in the example that you can use instead of setTimeout).
/** Wait for an async forEach loop. Does not run in parallel.
* @param {array[]} array - An input array
* @param {function} callback - A function to execute and await for each member of the array
* @author Sebastien Chopin
* @see {@link https://codeburst.io/javascript-async-await-with-foreach-b6ba62bbf404|Sebastien's Medium article} for more information
* @example
* const waitFor = (ms) => new Promise(r => setTimeout(r, ms));
*
* await asyncForEach([1, 2, 3], async (num) => {
* await waitFor(50);
* console.log(num);
* });
* console.log('Done');
*/
export async function asyncForEach(array, callback) {
for (let index = 0; index < array.length; index++) {
await callback(array[index], index, array);
}
};
More difficult tips:
[DIGITAL_MESSAGE](board)
method and then listen for that instead of listening for all 8 pins. If portValue changes between linha reads then you know a piece has moved:
board.emit(`digital-read-port-${port}`, portValue);
Thank you for all the help you gave me, I'll try to clean my code following this tips. I've tried to use async/await insted of callbacks but without sucess, for sure was some mistake I was making, I'll try it again, thank you!
Hi guys I`m having problems to control the board.loop feature, my code is running asynchronous and I could not make it working adding awaits or something like that, it always run out of order, my console output for that code is that. Someone can help me to understand what should I do? thanks!!