Testing gpio interface
This commit is contained in:
parent
c0fe29a204
commit
9d084ee37a
36
README.md
36
README.md
@ -2,7 +2,41 @@
|
|||||||
Node.js Raspberry Pi Pellet Stove Controller, named after the Greek virgin goddess of the hearth.
|
Node.js Raspberry Pi Pellet Stove Controller, named after the Greek virgin goddess of the hearth.
|
||||||
|
|
||||||
# About
|
# About
|
||||||
This project seeks to replace the OEM control panel on a Lennox Winslow PS40 pellet stove with a Raspberry Pi. I will be utilizing a Raspberry Pi Zero W, relays, and switches already installed on the pellet stove. I chose a Pi Zero W for its small form factor, the lack of pre-installed headers, its wireless connectivity, and familiarity with the platform. I had previously used an Arduino Nano for a much more rudimentary version of this project and found great difficulty in making adjustments to the code. Additionally the Raspberry Pi platform will allow for expansion in the future to include IoT controls and logging of usage utilizing networked databases. The project will be written using Node.js and the rpi-gpio Node module. I've chosen Node.js for its familiarity as well as ease of implementation of a web server for future expansion.
|
This project seeks to replace the OEM control panel on a Lennox Winslow PS40 pellet stove with a Raspberry Pi. I am utilizing a Raspberry Pi 3 Model B+, relays, and temperature snap switches installed on the pellet stove. I chose a Pi 3 for its wireless connectivity and familiarity with the platform. I had previously used an Arduino Nano for a much more rudimentary version of this project and found great difficulty in making adjustments to the code. Additionally the Raspberry Pi platform will allow for expansion in the future to include IoT controls and logging of usage utilizing networked databases. The project will be written using Node.js to handle high-level logic and communications, calling Python scripts to handle interacting with GPIO. I'm now in the process of rewriting this project to a more modern v2. Previously I had settled on using deprecated versions of Node.js to maintain compatibility with various Pi GPIO modules, now I've decided to split the GPIO controls off to a small Python interface script.
|
||||||
|
|
||||||
|
# Logic Flow
|
||||||
|
|
||||||
|
### Boot
|
||||||
|
* Server starts
|
||||||
|
* Call python to check pin states and reset them
|
||||||
|
* Establish connection to MQTT
|
||||||
|
* Listen for messages published to MQTT
|
||||||
|
|
||||||
|
### Auto-Start
|
||||||
|
* Check pin states for safety
|
||||||
|
* Power on igniter, 30 second pre-heat
|
||||||
|
* Power on exhaust
|
||||||
|
* Power on auger
|
||||||
|
* Wait X minutes
|
||||||
|
* Check Proof of Fire switch
|
||||||
|
* No Fire:
|
||||||
|
* Shutdown
|
||||||
|
* Alert
|
||||||
|
* Fire:
|
||||||
|
*Power off igniter
|
||||||
|
|
||||||
|
### Shutdown
|
||||||
|
* Check pin states
|
||||||
|
* Power off auger
|
||||||
|
* Wait X minutes
|
||||||
|
* Check Proof of Fire switch
|
||||||
|
* No Fire:
|
||||||
|
* Wait X minutes
|
||||||
|
* Power off exhaust
|
||||||
|
* Fire:
|
||||||
|
* Wait X minutes
|
||||||
|
* Repeat PoF switch check
|
||||||
|
|
||||||
|
|
||||||
# GPIO
|
# GPIO
|
||||||
Three GPIO pins are used along with a common ground to control three relays, supplying 120VAC power to the igniter and combustion blower when appropriate, and supplying power to the auger motor in pulses. Two more GPIO pins are used to detect open/closed status of a temperature-controlled snap switch and a vacuum switch. Another temperature-controlled snap switch is used to supply power to the convection motor when the pellet stove has reached a suitable temperature. A final temperature-controlled snap switch us used to interrupt the circuit for the auger motor to shut the stove off when an over-temperature condition is met. I will be utilizing a OneWire DS18B20 temperature sensor to detect the temperature of air exiting the stove vents.
|
Three GPIO pins are used along with a common ground to control three relays, supplying 120VAC power to the igniter and combustion blower when appropriate, and supplying power to the auger motor in pulses. Two more GPIO pins are used to detect open/closed status of a temperature-controlled snap switch and a vacuum switch. Another temperature-controlled snap switch is used to supply power to the convection motor when the pellet stove has reached a suitable temperature. A final temperature-controlled snap switch us used to interrupt the circuit for the auger motor to shut the stove off when an over-temperature condition is met. I will be utilizing a OneWire DS18B20 temperature sensor to detect the temperature of air exiting the stove vents.
|
||||||
|
44
src/main.js
44
src/main.js
@ -1,5 +1,39 @@
|
|||||||
// Hestia Control Panel Back-End
|
const { exec } = require('child_process');
|
||||||
import { State, Communicator } from './custom_modules/HestiaClasses';
|
|
||||||
import config from './custom_modules/config.json' assert { type: 'json' };
|
// List of pins to toggle
|
||||||
const psState = new State(config);
|
const pins = [7, 13, 15, 16, 18, 22];
|
||||||
const comm = new Communicator(psState);
|
|
||||||
|
// Function to toggle a pin
|
||||||
|
function togglePin(pin, callback) {
|
||||||
|
exec(`python3 src/python/gpio_interface.py toggle ${pin}`, (error, stdout, stderr) => {
|
||||||
|
if (error) {
|
||||||
|
console.error(`Error toggling pin ${pin}: ${error.message}`);
|
||||||
|
return callback(error);
|
||||||
|
}
|
||||||
|
if (stderr) {
|
||||||
|
console.error(`Stderr while toggling pin ${pin}: ${stderr}`);
|
||||||
|
return callback(new Error(stderr));
|
||||||
|
}
|
||||||
|
console.log(`Successfully toggled pin ${pin}`);
|
||||||
|
callback(null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Toggle all pins
|
||||||
|
function toggleAllPins(pins, index = 0) {
|
||||||
|
if (index >= pins.length) {
|
||||||
|
console.log('All pins toggled.');
|
||||||
|
process.exit(0); // Exit successfully
|
||||||
|
} else {
|
||||||
|
togglePin(pins[index], (err) => {
|
||||||
|
if (err) {
|
||||||
|
process.exit(1); // Exit with error
|
||||||
|
} else {
|
||||||
|
setTimeout(() => toggleAllPins(pins, index + 1), 1000); // 1-second delay between toggles
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start toggling pins
|
||||||
|
toggleAllPins(pins);
|
63
src/python/gpio_interface.py
Normal file
63
src/python/gpio_interface.py
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import RPi.GPIO as GPIO
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
|
# Initialize GPIO
|
||||||
|
GPIO.setmode(GPIO.BCM)
|
||||||
|
GPIO.setwarnings(False)
|
||||||
|
|
||||||
|
# Define pin modes and states
|
||||||
|
def setup_pin(pin, mode):
|
||||||
|
if mode == 'OUT':
|
||||||
|
GPIO.setup(pin, GPIO.OUT)
|
||||||
|
elif mode == 'IN':
|
||||||
|
GPIO.setup(pin, GPIO.IN)
|
||||||
|
|
||||||
|
def toggle_pin(pin):
|
||||||
|
setup_pin(pin, 'OUT')
|
||||||
|
current_state = GPIO.input(pin)
|
||||||
|
try:
|
||||||
|
# Toggle pin state
|
||||||
|
GPIO.output(pin, GPIO.LOW if current_state == GPIO.HIGH else GPIO.HIGH)
|
||||||
|
# Exit with 0 for success
|
||||||
|
return 0
|
||||||
|
except Exception as e:
|
||||||
|
# Handle errors
|
||||||
|
print(f"Error toggling pin {pin}: {e}")
|
||||||
|
# Exit with 1 for failure
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def sense_pin(pin):
|
||||||
|
setup_pin(pin, 'IN')
|
||||||
|
try:
|
||||||
|
# Sense pin state
|
||||||
|
state = GPIO.input(pin)
|
||||||
|
# Return 1 if pin is HIGH, 0 if LOW
|
||||||
|
return 1 if state == GPIO.HIGH else 0
|
||||||
|
except Exception as e:
|
||||||
|
# Handle errors
|
||||||
|
print(f"Error sensing pin {pin}: {e}")
|
||||||
|
# Return -1 on error
|
||||||
|
return -1
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print("Usage: python3 gpio_interface.py <command> <pin>")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
command = sys.argv[1].lower()
|
||||||
|
pin = int(sys.argv[2])
|
||||||
|
|
||||||
|
if command == "toggle":
|
||||||
|
result = toggle_pin(pin)
|
||||||
|
sys.exit(result)
|
||||||
|
elif command == "sense":
|
||||||
|
result = sense_pin(pin)
|
||||||
|
print(result)
|
||||||
|
sys.exit(0 if result >= 0 else 1)
|
||||||
|
else:
|
||||||
|
print("Invalid command. Use 'toggle' or 'sense'.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
Loading…
Reference in New Issue
Block a user