Libraries and examples for Automation 2040 W (#418)

* Libraries and examples for Automation 2040 W

* Fix for initialisation error
examples/inky_pack
ZodiusInfuser 2022-07-01 07:05:37 +01:00 zatwierdzone przez GitHub
rodzic 93e1da21b2
commit d9d8f4417a
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
26 zmienionych plików z 1166 dodań i 0 usunięć

Wyświetl plik

@ -45,6 +45,7 @@ add_subdirectory(pico_wireless)
add_subdirectory(inky_pack)
add_subdirectory(automation2040w)
add_subdirectory(plasma2040)
add_subdirectory(badger2040)
add_subdirectory(tufty2040)

Wyświetl plik

@ -0,0 +1,5 @@
include(automation2040w_read_adcs.cmake)
include(automation2040w_read_inputs.cmake)
include(automation2040w_switches_and_leds.cmake)
include(automation2040w_toggle_outputs.cmake)
include(automation2040w_toggle_relays.cmake)

Wyświetl plik

@ -0,0 +1,40 @@
# Automation 2040 W C++ Examples <!-- omit in toc -->
- [Function Examples](#function-examples)
- [Read ADCs](#read-adcs)
- [Read Inputs](#read-inputs)
- [Toggle Relays](#toggle-relays)
- [Toggle Outputs](#toggle-outputs)
- [Switches and LEDs](#switches-and-leds)
## Function Examples
### Read ADCs
[automation2040w_read_adcs.cpp](automation2040w_read_adcs.cpp)
Shows how to read the 3 ADC terminals of Automation 2040 W.
### Read Inputs
[automation2040w_read_inputs.cpp](automation2040w_read_inputs.cpp)
Shows how to read the 3 Input terminals of Automation 2040 W.
### Toggle Relays
[automation2040w_toggle_relays.cpp](automation2040w_toggle_relays.cpp)
Demonstrates how to toggle the actuation state of each of Automation 2040 W's relays.
### Toggle Outputs
[automation2040w_toggle_outputs.cpp](automation2040w_toggle_outputs.cpp)
Demonstrates how to toggle each of Automation 2040 W's output terminals.
### Switches and LEDs
[automation2040w_switches_and_leds.cpp](automation2040w_switches_and_leds.cpp)
An example of the user switches and LEDs on Automation 2040 W.

Wyświetl plik

@ -0,0 +1,14 @@
set(OUTPUT_NAME automation2040w_read_adcs)
add_executable(${OUTPUT_NAME} automation2040w_read_adcs.cpp)
# Pull in pico libraries that we need
target_link_libraries(${OUTPUT_NAME}
pico_stdlib
automation
)
# enable usb output
pico_enable_stdio_usb(${OUTPUT_NAME} 1)
# create map/bin/hex file etc.
pico_add_extra_outputs(${OUTPUT_NAME})

Wyświetl plik

@ -0,0 +1,52 @@
#include <cstdio>
#include "pico/stdlib.h"
#include "automation.hpp"
/*
Shows how to read the 3 ADC terminals of Automation 2040 W.
Press "A" to exit the program.
*/
using namespace automation;
// How many times to update per second
const uint UPDATES = 10;
// The friendly names to give each ADC input
const char* ADC_NAMES[] = {"A1", "A2", "A3"};
// Create a new Automation2040W
Automation2040W board;
int main() {
stdio_init_all();
// Attempt to initialise the board
if(board.init()) {
// Enable the LED of the switch used to exit the loop
board.switch_led(SWITCH_A, 50.0f); // Half Brightness
// Read the ADCs until user switch is pressed
while(!board.switch_pressed(SWITCH_A)) {
// Read each ADC in turn and print its voltage
for(uint i = 0; i < NUM_ADCS; i++) {
float voltage = board.read_adc(i);
printf("%s = %f, ", ADC_NAMES[i], voltage);
}
// Print a new line
printf("\n");
sleep_ms(1000 / UPDATES);
}
// Put the board back into a safe state
board.reset();
}
}

Wyświetl plik

@ -0,0 +1,14 @@
set(OUTPUT_NAME automation2040w_read_inputs)
add_executable(${OUTPUT_NAME} automation2040w_read_inputs.cpp)
# Pull in pico libraries that we need
target_link_libraries(${OUTPUT_NAME}
pico_stdlib
automation
)
# enable usb output
pico_enable_stdio_usb(${OUTPUT_NAME} 1)
# create map/bin/hex file etc.
pico_add_extra_outputs(${OUTPUT_NAME})

Wyświetl plik

@ -0,0 +1,52 @@
#include <cstdio>
#include "pico/stdlib.h"
#include "automation.hpp"
/*
Shows how to read the 3 Input terminals of Automation 2040 W.
Press "A" to exit the program.
*/
using namespace automation;
// How many times to update per second
const uint UPDATES = 10;
// The friendly names to give each digital input
const char* INPUT_NAMES[] = {"I1", "I2", "I3", "I4"};
// Create a new Automation2040W
Automation2040W board;
int main() {
stdio_init_all();
// Attempt to initialise the board
if(board.init()) {
// Enable the LED of the switch used to exit the loop
board.switch_led(SWITCH_A, 50.0f); // Half Brightness
// Read the inputs until user switch is pressed
while(!board.switch_pressed(SWITCH_A)) {
// Read each input in turn and print its voltage
for(uint i = 0; i < NUM_INPUTS; i++) {
bool value = board.read_input(i);
printf("%s = %d, ", INPUT_NAMES[i], (int)value);
}
// Print a new line
printf("\n");
sleep_ms(1000 / UPDATES);
}
// Put the board back into a safe state
board.reset();
}
}

Wyświetl plik

@ -0,0 +1,14 @@
set(OUTPUT_NAME automation2040w_switches_and_leds)
add_executable(${OUTPUT_NAME} automation2040w_switches_and_leds.cpp)
# Pull in pico libraries that we need
target_link_libraries(${OUTPUT_NAME}
pico_stdlib
automation
)
# enable usb output
pico_enable_stdio_usb(${OUTPUT_NAME} 1)
# create map/bin/hex file etc.
pico_add_extra_outputs(${OUTPUT_NAME})

Wyświetl plik

@ -0,0 +1,66 @@
#include <cstdio>
#include "pico/stdlib.h"
#include "automation.hpp"
/*
An example of the user switches and LEDs on Automation 2040 W.
Press "A" and "B" together to exit the program.
*/
using namespace automation;
// How many times to update per second
const uint UPDATES = 10;
// The friendly names to give each user input
const char* SWITCH_NAMES[] = {"SW_A", "SW_B"};
// How much to change a LED's brightess each update
const uint LED_INCREMENT = 2;
// Create a new Automation2040W
Automation2040W board;
int main() {
stdio_init_all();
// Attempt to initialise the board
if(board.init()) {
// Enable the Conn LED
board.conn_led(true); // Full Brightness
float led_brightnesses[] = {0.0f, 0.0f};
// Interact with the switches and LEDs until both are pressed simultaneously
while(!board.switch_pressed(SWITCH_A) || !board.switch_pressed(SWITCH_B)) {
for(uint i = 0; i < NUM_SWITCHES; i++) {
// Change the LED brightness based on switch's state
if(board.switch_pressed(i)) {
printf("%s = Pressed, ", SWITCH_NAMES[i]);
led_brightnesses[i] = MIN(led_brightnesses[i] + LED_INCREMENT, 100.0f);
}
else {
printf("%s = Released, ", SWITCH_NAMES[i]);
led_brightnesses[i] = MAX(led_brightnesses[i] - LED_INCREMENT, 0.0f);
}
// Apply the new brightnesses to the LEDs
board.switch_led(i, led_brightnesses[i]);
}
// Print a new line
printf("\n");
sleep_ms(1000 / UPDATES);
}
// Put the board back into a safe state
board.reset();
}
}

Wyświetl plik

@ -0,0 +1,14 @@
set(OUTPUT_NAME automation2040w_toggle_outputs)
add_executable(${OUTPUT_NAME} automation2040w_toggle_outputs.cpp)
# Pull in pico libraries that we need
target_link_libraries(${OUTPUT_NAME}
pico_stdlib
automation
)
# enable usb output
pico_enable_stdio_usb(${OUTPUT_NAME} 1)
# create map/bin/hex file etc.
pico_add_extra_outputs(${OUTPUT_NAME})

Wyświetl plik

@ -0,0 +1,63 @@
#include <cstdio>
#include "pico/stdlib.h"
#include "automation.hpp"
/*
Demonstrates how to toggle each of Automation 2040 W's output terminals.
Press "A" to exit the program.
*/
using namespace automation;
// How much time to wait between each toggle (in milliseconds)
const uint TIME_PER_TOGGLE_MS = 500;
// The friendly names to give each digital output
const char* OUTPUT_NAMES[] = {"O1", "O2", "O3"};
// Create a new Automation2040W
Automation2040W board;
int main() {
stdio_init_all();
// Attempt to initialise the board
if(board.init()) {
// Enable the LED of the switch used to exit the loop
board.switch_led(SWITCH_A, 50.0f); // Half Brightness
bool toggle = true;
uint index = 0;
// Toggle the outputs until the user switch is pressed
while(!board.switch_pressed(SWITCH_A)) {
// Toggle an output
board.output(index, toggle);
// Print the state of all outputs
for(uint i = 0; i < NUM_OUTPUTS; i++) {
printf("%s = %d, ", OUTPUT_NAMES[i], (int)board.output(i));
}
// Print a new line
printf("\n");
index++; // Move on to the next output
if(index >= NUM_OUTPUTS) {
index = 0; // Go back to the first output
toggle = !toggle; // Invert the toggle value
}
sleep_ms(TIME_PER_TOGGLE_MS);
}
// Put the board back into a safe state
board.reset();
}
}

Wyświetl plik

@ -0,0 +1,14 @@
set(OUTPUT_NAME automation2040w_toggle_relays)
add_executable(${OUTPUT_NAME} automation2040w_toggle_relays.cpp)
# Pull in pico libraries that we need
target_link_libraries(${OUTPUT_NAME}
pico_stdlib
automation
)
# enable usb output
pico_enable_stdio_usb(${OUTPUT_NAME} 1)
# create map/bin/hex file etc.
pico_add_extra_outputs(${OUTPUT_NAME})

Wyświetl plik

@ -0,0 +1,63 @@
#include <cstdio>
#include "pico/stdlib.h"
#include "automation.hpp"
/*
Demonstrates how to toggle the actuation state of each of Automation 2040 W's relays.
Press "A" to exit the program.
*/
using namespace automation;
// How much time to wait between each toggle (in milliseconds)
const uint TIME_PER_TOGGLE_MS = 500;
// The friendly names to give each relay
const char* RELAY_NAMES[] = {"R1", "R2", "R3"};
// Create a new Automation2040W
Automation2040W board;
int main() {
stdio_init_all();
// Attempt to initialise the board
if(board.init()) {
// Enable the LED of the switch used to exit the loop
board.switch_led(SWITCH_A, 50.0f); // Half Brightness
bool toggle = true;
uint index = 0;
// Toggle the relays until the user switch is pressed
while(!board.switch_pressed(SWITCH_A)) {
// Toggle a relay
board.relay(index, toggle);
// Print the state of all relays
for(uint i = 0; i < NUM_RELAYS; i++) {
printf("%s = %d, ", RELAY_NAMES[i], (int)board.relay(i));
}
// Print a new line
printf("\n");
index++; // Move on to the next relay
if(index >= NUM_RELAYS) {
index = 0; // Go back to the first relay
toggle = !toggle; // Invert the toggle value
}
sleep_ms(TIME_PER_TOGGLE_MS);
}
// Put the board back into a safe state
board.reset();
}
}

Wyświetl plik

@ -25,6 +25,7 @@ add_subdirectory(pico_explorer)
add_subdirectory(pico_motor_shim)
add_subdirectory(pico_rgb_keypad)
add_subdirectory(pico_wireless)
add_subdirectory(automation2040w)
add_subdirectory(plasma2040)
add_subdirectory(badger2040)
add_subdirectory(tufty2040)

Wyświetl plik

@ -0,0 +1 @@
include(automation.cmake)

Wyświetl plik

@ -0,0 +1,12 @@
add_library(automation INTERFACE)
target_sources(automation INTERFACE
${CMAKE_CURRENT_LIST_DIR}/automation.cpp
)
target_include_directories(automation INTERFACE ${CMAKE_CURRENT_LIST_DIR})
#include(${PIMORONI_PICO_PATH}/drivers/analog/analog.cmake)
# Pull in pico libraries that we need
target_link_libraries(automation INTERFACE pico_stdlib hardware_pwm hardware_i2c pimoroni_i2c analog)

Wyświetl plik

@ -0,0 +1,178 @@
#include <math.h>
#include "automation.hpp"
namespace automation {
const uint Automation2040W::ADC_LED_PINS[] = {6, 7, 8};
const uint Automation2040W::RELAY_PINS[] = {9, 10, 11};
const uint Automation2040W::USER_SW_PINS[] = {12, 13};
const uint Automation2040W::USER_LED_PINS[] = {14, 15};
const uint Automation2040W::OUTPUT_PINS[] = {16, 17, 18};
const uint Automation2040W::IN_BUFFERED_PINS[] = {19, 20, 21, 22};
const uint Automation2040W::ADC_PINS[] = {26, 27, 28};
Automation2040W::Automation2040W()
: i2c(I2C_SDA_PIN, I2C_SCL_PIN, 100000)
, analogs{Analog(ADC_PINS[0], VOLTAGE_GAIN, 0.0f, VOLTAGE_OFFSET),
Analog(ADC_PINS[1], VOLTAGE_GAIN, 0.0f, VOLTAGE_OFFSET),
Analog(ADC_PINS[2], VOLTAGE_GAIN, 0.0f, VOLTAGE_OFFSET)} {
}
bool Automation2040W::init() {
// Set up the relay pins
for(auto i = 0u; i < NUM_RELAYS; i++) {
gpio_set_function(RELAY_PINS[i], GPIO_FUNC_SIO);
gpio_set_dir(RELAY_PINS[i], GPIO_OUT);
release_relay(i);
}
// Set up the output pins
for(auto i = 0u; i < NUM_OUTPUTS; i++) {
gpio_set_function(OUTPUT_PINS[i], GPIO_FUNC_SIO);
gpio_set_dir(OUTPUT_PINS[i], GPIO_OUT);
output(i, false);
}
// Set up the input pins
for(auto i = 0u; i < NUM_INPUTS; i++) {
gpio_set_function(IN_BUFFERED_PINS[i], GPIO_FUNC_SIO);
gpio_set_dir(IN_BUFFERED_PINS[i], GPIO_IN);
}
// Set up the adc leds
for(auto i = 0u; i < NUM_ADCS; i++) {
gpio_put(ADC_LED_PINS[i], false);
pwm_config cfg = pwm_get_default_config();
pwm_set_wrap(pwm_gpio_to_slice_num(ADC_LED_PINS[i]), 65535);
pwm_init(pwm_gpio_to_slice_num(ADC_LED_PINS[i]), &cfg, true);
gpio_set_function(ADC_LED_PINS[i], GPIO_FUNC_PWM);
pwm_set_gpio_level(ADC_LED_PINS[i], 0);
}
// Set up the user switches and LEDs
for(auto i = 0u; i < NUM_SWITCHES; i++) {
gpio_set_function(USER_SW_PINS[i], GPIO_FUNC_SIO);
gpio_set_dir(USER_SW_PINS[i], GPIO_IN);
gpio_pull_up(USER_SW_PINS[i]);
gpio_put(USER_LED_PINS[i], false);
pwm_config cfg = pwm_get_default_config();
pwm_set_wrap(pwm_gpio_to_slice_num(USER_LED_PINS[i]), 65535);
pwm_init(pwm_gpio_to_slice_num(USER_LED_PINS[i]), &cfg, true);
gpio_set_function(USER_LED_PINS[i], GPIO_FUNC_PWM);
pwm_set_gpio_level(USER_LED_PINS[i], 0);
}
// Set up the connectivity LED
gpio_put(CONN_LED_PIN, false);
pwm_config cfg = pwm_get_default_config();
pwm_set_wrap(pwm_gpio_to_slice_num(CONN_LED_PIN), 65535);
pwm_init(pwm_gpio_to_slice_num(CONN_LED_PIN), &cfg, true);
gpio_set_function(CONN_LED_PIN, GPIO_FUNC_PWM);
pwm_set_gpio_level(CONN_LED_PIN, 0);
return true; // We just return true for now, but could expand in the future
}
void Automation2040W::conn_led(bool on) {
pwm_set_gpio_level(CONN_LED_PIN, on ? 65535 : 0);
}
void Automation2040W::conn_led(float brightness) {
brightness = CLAMP(brightness, 0.0f, 100.0f);
const float gamma = 2.8f;
uint16_t value = (uint16_t)(powf(brightness / 100.0f, gamma) * 65535.0f + 0.5f);
pwm_set_gpio_level(CONN_LED_PIN, value);
}
bool Automation2040W::switch_pressed(uint sw) {
assert(sw < NUM_SWITCHES);
return !gpio_get(USER_SW_PINS[sw]);
}
void Automation2040W::switch_led(uint sw, bool on) {
assert(sw < NUM_SWITCHES);
pwm_set_gpio_level(USER_LED_PINS[sw], on ? 65535 : 0);
}
void Automation2040W::switch_led(uint sw, float brightness) {
assert(sw < NUM_SWITCHES);
brightness = CLAMP(brightness, 0.0f, 100.0f);
const float gamma = 2.8f;
uint16_t value = (uint16_t)(powf(brightness / 100.0f, gamma) * 65535.0f + 0.5f);
pwm_set_gpio_level(USER_LED_PINS[sw], value);
}
bool Automation2040W::relay(uint relay) {
assert(relay < NUM_RELAYS);
return gpio_get(RELAY_PINS[relay]);
}
void Automation2040W::relay(uint relay, bool actuate) {
assert(relay < NUM_RELAYS);
gpio_put(RELAY_PINS[relay], actuate);
}
void Automation2040W::actuate_relay(uint relay) {
assert(relay < NUM_RELAYS);
gpio_put(RELAY_PINS[relay], true);
}
void Automation2040W::release_relay(uint relay) {
assert(relay < NUM_RELAYS);
gpio_put(RELAY_PINS[relay], false);
}
bool Automation2040W::output(uint output) {
assert(output < NUM_OUTPUTS);
return gpio_get(OUTPUT_PINS[output]);
}
void Automation2040W::output(uint output, bool value) {
assert(output < NUM_OUTPUTS);
gpio_put(OUTPUT_PINS[output], value);
}
bool Automation2040W::read_input(uint input) {
assert(input < NUM_INPUTS);
return gpio_get(IN_BUFFERED_PINS[input]);
}
float Automation2040W::read_adc(uint adc) {
assert(adc < NUM_ADCS);
float voltage = analogs[adc].read_voltage();
const float gamma = 2.8f;
uint16_t value = (uint16_t)(powf(voltage / MAX_ADC_LED_VOLTAGE, gamma) * 65535.0f + 0.5f);
pwm_set_gpio_level(ADC_LED_PINS[adc], value);
return voltage;
}
void Automation2040W::reset() {
// Reset the relays
for(auto i = 0u; i < NUM_RELAYS; i++) {
release_relay(i);
}
// Reset the outputs
for(auto i = 0u; i < NUM_OUTPUTS; i++) {
output(i, false);
}
// Reset the adc leds
for(auto i = 0u; i < NUM_ADCS; i++) {
pwm_set_gpio_level(ADC_LED_PINS[i], 0);
}
// Reset the switch LEDs
for(auto i = 0u; i < NUM_SWITCHES; i++) {
pwm_set_gpio_level(USER_LED_PINS[i], 0);
}
// Reset the connectivity LED
pwm_set_gpio_level(CONN_LED_PIN, 0);
}
}

Wyświetl plik

@ -0,0 +1,113 @@
#pragma once
#include "pico/stdlib.h"
#include "hardware/pwm.h"
#include "analog.hpp"
#include "pimoroni_i2c.hpp"
using namespace pimoroni;
namespace automation {
// IO Pin Constants
const uint GP0 = 0;
const uint GP1 = 1;
const uint GP2 = 2;
// Index Constants
const uint RELAY_1 = 0;
const uint RELAY_2 = 1;
const uint RELAY_3 = 2;
const uint OUTPUT_1 = 0;
const uint OUTPUT_2 = 1;
const uint OUTPUT_3 = 2;
const uint ADC_1 = 0;
const uint ADC_2 = 1;
const uint ADC_3 = 2;
const uint INPUT_1 = 0;
const uint INPUT_2 = 1;
const uint INPUT_3 = 2;
const uint INPUT_4 = 3;
const uint SWITCH_A = 0;
const uint SWITCH_B = 1;
// Count Constants
const uint NUM_GPIOS = 3;
const uint NUM_RELAYS = 3;
const uint NUM_OUTPUTS = 3;
const uint NUM_ADCS = 3;
const uint NUM_INPUTS = 4;
const uint NUM_SWITCHES = 2;
class Automation2040W {
//--------------------------------------------------
// Constants
//--------------------------------------------------
public:
static const uint CONN_LED_PIN = 3;
static const uint I2C_SDA_PIN = 4;
static const uint I2C_SCL_PIN = 5;
static const uint ADC_LED_PINS[];
static const uint RELAY_PINS[];
static const uint USER_SW_PINS[];
static const uint USER_LED_PINS[];
static const uint OUTPUT_PINS[];
static const uint IN_BUFFERED_PINS[];
static const uint ADC_PINS[];
static constexpr float VOLTAGE_GAIN = 0.06f; // 56 / (56 + 820)
static constexpr float VOLTAGE_OFFSET = -0.06f;
static constexpr float MAX_ADC_LED_VOLTAGE = 45.0f;
//--------------------------------------------------
// Variables
//--------------------------------------------------
public:
I2C i2c;
private:
Analog analogs[NUM_ADCS];
//--------------------------------------------------
// Constructors/Destructor
//--------------------------------------------------
public:
Automation2040W();
//--------------------------------------------------
// Methods
//--------------------------------------------------
public:
bool init();
void conn_led(bool on);
void conn_led(float brightness);
bool switch_pressed(uint sw);
void switch_led(uint sw, bool on);
void switch_led(uint sw, float brightness);
bool relay(uint relay);
void relay(uint relay, bool actuate);
void actuate_relay(uint relay);
void release_relay(uint relay);
bool output(uint output);
void output(uint output, bool value);
bool read_input(uint input);
float read_adc(uint adc);
void reset();
};
}

Wyświetl plik

@ -0,0 +1,47 @@
# Automation 2040 W Micropython Examples <!-- omit in toc -->
- [Function Examples](#function-examples)
- [Read ADCs](#read-adcs)
- [Read Inputs](#read-inputs)
- [Toggle Relays](#toggle-relays)
- [Toggle Outputs](#toggle-outputs)
- [Switches and LEDs](#switches-and-leds)
- [Reset Automation](#reset-automation)
## Function Examples
### Read ADCs
[read_adcs.py](read_adcs.py)
Shows how to read the 3 ADC terminals of Automation 2040 W.
### Read Inputs
[read_inputs.py](read_inputs.py)
Shows how to read the 3 Input terminals of Automation 2040 W.
### Toggle Relays
[toggle_relays.py](toggle_relays.py)
Demonstrates how to toggle the actuation state of each of Automation 2040 W's relays.
### Toggle Outputs
[toggle_outputs.py](toggle_outputs.py)
Demonstrates how to toggle each of Automation 2040 W's output terminals.
### Switches and LEDs
[switches_and_leds.py](switches_and_leds.py)
An example of the user switches and LEDs on Automation 2040 W.
### Reset Automation
[reset_automation.py](reset_automation.py)
A simple program that resets Automation 2040 W, turning off its Relays, Outputs, and LEDs.

Wyświetl plik

@ -0,0 +1,33 @@
import time
from automation import Automation2040W, SWITCH_A, NUM_ADCS
"""
Shows how to read the 3 ADC terminals of Automation 2040 W.
Press "A" to exit the program.
"""
UPDATES = 10 # How many times to update per second
ADC_NAMES = ("A1", "A2", "A3") # The friendly names to give each ADC input
# Create a new Automation2040W
board = Automation2040W()
# Enable the LED of the switch used to exit the loop
board.switch_led(SWITCH_A, 50) # Half Brightness
# Read the ADCs until the user switch is pressed
while not board.switch_pressed(SWITCH_A):
# Read each ADC in turn and print its voltage
for i in range(NUM_ADCS):
voltage = board.read_adc(i)
print(ADC_NAMES[i], " = ", round(voltage, 3), sep="", end=", ")
# Print a new line
print()
time.sleep(1.0 / UPDATES)
# Put the board back into a safe state
board.reset()

Wyświetl plik

@ -0,0 +1,33 @@
import time
from automation import Automation2040W, SWITCH_A, NUM_INPUTS
"""
Shows how to read the 3 Input terminals of Automation 2040 W.
Press "A" to exit the program.
"""
UPDATES = 10 # How many times to update per second
INPUT_NAMES = ("I1", "I2", "I3", "I4") # The friendly names to give each digital input
# Create a new Automation2040W
board = Automation2040W()
# Enable the LED of the switch used to exit the loop
board.switch_led(SWITCH_A, 50) # Half Brightness
# Read the inputs until the user switch is pressed
while not board.switch_pressed(SWITCH_A):
# Read each input in turn and print its value
for i in range(NUM_INPUTS):
value = board.read_input(i)
print(INPUT_NAMES[i], " = ", value, sep="", end=", ")
# Print a new line
print()
time.sleep(1.0 / UPDATES)
# Put the board back into a safe state
board.reset()

Wyświetl plik

@ -0,0 +1,8 @@
from automation import Automation2040W
"""
A simple program that resets Automation 2040 W,
turning off its Relays, Outputs, and LEDs.
"""
board = Automation2040W()

Wyświetl plik

@ -0,0 +1,43 @@
import time
from automation import Automation2040W, SWITCH_A, SWITCH_B, NUM_SWITCHES
"""
An example of the user switches and LEDs on Automation 2040 W.
Press "A" and "B" together to exit the program.
"""
UPDATES = 10 # How many times to update per second
SWITCH_NAMES = ("SW_A", "SW_B") # The friendly names to give each user switch
LED_INCREMENT = 2 # How much to change a LED's brightess each update
# Create a new Automation2040W
board = Automation2040W()
# Enable the Conn LED
board.conn_led(True) # Full Brightness
led_brightnesses = [0.0, 0.0]
# Interact with the switches and LEDs until both are pressed simultaneously
while not board.switch_pressed(SWITCH_A) or not board.switch_pressed(SWITCH_B):
for i in range(NUM_SWITCHES):
# Change the LED brightness based on switch's state
if board.switch_pressed(i):
print(SWITCH_NAMES[i], " = Pressed", sep="", end=", ")
led_brightnesses[i] = min(led_brightnesses[i] + LED_INCREMENT, 100)
else:
print(SWITCH_NAMES[i], " = Released", sep="", end=", ")
led_brightnesses[i] = max(led_brightnesses[i] - LED_INCREMENT, 0)
# Apply the new brightnesses to the LEDs
board.switch_led(i, led_brightnesses[i])
# Print a new line
print()
time.sleep(1.0 / UPDATES)
# Put the board back into a safe state
board.reset()

Wyświetl plik

@ -0,0 +1,43 @@
import time
from automation import Automation2040W, SWITCH_A, NUM_OUTPUTS
"""
Demonstrates how to toggle each of Automation 2040 W's output terminals.
Press "A" to exit the program.
"""
TIME_PER_TOGGLE = 0.5 # How much time to wait between each toggle (in seconds)
OUTPUT_NAMES = ("O1", "O2", "O3") # The friendly names to give each digital output
# Create a new Automation2040W
board = Automation2040W()
# Enable the LED of the switch used to exit the loop
board.switch_led(SWITCH_A, 50) # Half Brightness
toggle = True
index = 0
# Toggle the outputs until the user switch is pressed
while not board.switch_pressed(SWITCH_A):
# Toggle an output
board.output(index, toggle)
# Print the state of all outputs
for i in range(NUM_OUTPUTS):
print(OUTPUT_NAMES[i], " = ", board.output(i), sep="", end=", ")
# Print a new line
print()
index += 1 # Move on to the next output
if index >= NUM_OUTPUTS:
index = 0 # Go back to the first output
toggle = not toggle # Invert the toggle value
time.sleep(TIME_PER_TOGGLE)
# Put the board back into a safe state
board.reset()

Wyświetl plik

@ -0,0 +1,43 @@
import time
from automation import Automation2040W, SWITCH_A, NUM_RELAYS
"""
Demonstrates how to toggle the actuation state of each of Automation 2040 W's relays.
Press "A" to exit the program.
"""
TIME_PER_TOGGLE = 0.5 # How much time to wait between each toggle (in seconds)
RELAY_NAMES = ("R1", "R2", "R3") # The friendly names to give each relay
# Create a new Automation2040W
board = Automation2040W()
# Enable the LED of the switch used to exit the loop
board.switch_led(SWITCH_A, 50) # Half Brightness
toggle = True
index = 0
# Toggle the relays until the user switch is pressed
while not board.switch_pressed(SWITCH_A):
# Toggle a relay
board.relay(index, toggle)
# Print the state of all relays
for i in range(NUM_RELAYS):
print(RELAY_NAMES[i], " = ", board.relay(i), sep="", end=", ")
# Print a new line
print()
index += 1 # Move on to the next relay
if index >= NUM_RELAYS:
index = 0 # Go back to the first relay
toggle = not toggle # Invert the toggle value
time.sleep(TIME_PER_TOGGLE)
# Put the board back into a safe state
board.reset()

Wyświetl plik

@ -0,0 +1,199 @@
import gc
from machine import Pin, PWM
from pimoroni_i2c import PimoroniI2C
from pimoroni import Analog
# IO Pin Constants
GP0 = 0
GP1 = 1
GP2 = 2
# Index Constants
RELAY_1 = 0
RELAY_2 = 1
RELAY_3 = 2
OUTPUT_1 = 0
OUTPUT_2 = 1
OUTPUT_3 = 2
ADC_1 = 0
ADC_2 = 1
ADC_3 = 2
INPUT_1 = 0
INPUT_2 = 1
INPUT_3 = 2
INPUT_4 = 3
SWITCH_A = 0
SWITCH_B = 1
# Count Constants
NUM_GPIOS = 3
NUM_RELAYS = 3
NUM_OUTPUTS = 3
NUM_ADCS = 3
NUM_INPUTS = 4
NUM_SWITCHES = 2
class Automation2040W():
CONN_LED_PIN = 3
I2C_SDA_PIN = 4
I2C_SCL_PIN = 5
ADC_LED_PINS = (6, 7, 8)
RELAY_PINS = (9, 10, 11)
USER_SW_PINS = (12, 13)
USER_LED_PINS = (14, 15)
OUTPUT_PINS = (16, 17, 18)
IN_BUFFERED_PINS = (19, 20, 21, 22)
ADC_PINS = (26, 27, 28)
VOLTAGE_GAIN = 0.06 # 56 / (56 + 820)
VOLTAGE_OFFSET = -0.06
MAX_ADC_LED_VOLTAGE = 45.0
def __init__(self):
# Free up hardware resources
gc.collect()
# Set up the i2c for Qw/st
self.i2c = PimoroniI2C(self.I2C_SDA_PIN, self.I2C_SCL_PIN, 100000)
# Set up the relay pins
self.__relays = []
for i in range(NUM_RELAYS):
self.__relays.append(Pin(self.RELAY_PINS[i], Pin.OUT))
self.release_relay(i)
# Set up the output pins
self.__outputs = []
for i in range(NUM_OUTPUTS):
self.__outputs.append(Pin(self.OUTPUT_PINS[i], Pin.OUT))
self.output(i, False)
# Set up the input pins
self.__inputs = []
for i in range(NUM_INPUTS):
self.__inputs.append(Pin(self.IN_BUFFERED_PINS[i], Pin.IN))
# Set up the adc pins and leds
self.__analogs = []
self.__adc_led_pwms = []
for i in range(NUM_ADCS):
self.__analogs.append(Analog(self.ADC_PINS[i], self.VOLTAGE_GAIN, offset=self.VOLTAGE_OFFSET))
led_pwm = PWM(Pin(self.ADC_LED_PINS[i]))
led_pwm.freq(1000)
led_pwm.duty_u16(0)
self.__adc_led_pwms.append(led_pwm)
# Set up the user switches
self.__switches = []
self.__switch_led_pwms = []
for i in range(NUM_SWITCHES):
self.__switches.append(Pin(self.USER_SW_PINS[i], Pin.IN, Pin.PULL_UP))
led_pwm = PWM(Pin(self.USER_LED_PINS[i]))
led_pwm.freq(1000)
led_pwm.duty_u16(0)
self.__switch_led_pwms.append(led_pwm)
# Set up the connectivity LED
self.__conn_led_pwm = PWM(Pin(self.CONN_LED_PIN))
self.__conn_led_pwm.freq(1000)
self.__conn_led_pwm.duty_u16(0)
def conn_led(self, brightness):
if brightness is True:
self.__conn_led_pwm.duty_u16(65535)
elif brightness is False:
self.__conn_led_pwm.duty_u16(0)
elif brightness < 0.0 or brightness > 100.0:
raise ValueError("brightness out of range. Expected 0 to 100, or True or False")
else:
gamma = 2.8
value = int(pow(brightness / 100.0, gamma) * 65535 + 0.5)
self.__conn_led_pwm.duty_u16(value)
def switch_pressed(self, switch):
if switch < 0 or switch > NUM_SWITCHES:
raise ValueError("switch out of range. Expected SWITCH_A (0) or SWITCH_B (1)")
return not self.__switches[switch].value()
def switch_led(self, switch, brightness):
if switch < 0 or switch > NUM_SWITCHES:
raise ValueError("switch out of range. Expected SWITCH_A (0) or SWITCH_B (1)")
if brightness is True:
self.__switch_led_pwms[switch].duty_u16(65535)
elif brightness is False:
self.__switch_led_pwms[switch].duty_u16(0)
elif brightness < 0.0 or brightness > 100.0:
raise ValueError("brightness out of range. Expected 0 to 100, or True or False")
else:
gamma = 2.8
value = int(pow(brightness / 100.0, gamma) * 65535 + 0.5)
self.__switch_led_pwms[switch].duty_u16(value)
def relay(self, relay, actuate=None):
if relay < 0 or relay > NUM_RELAYS:
raise ValueError("relay out of range. Expected RELAY_1 (0), RELAY_2 (1), or RELAY_3 (2)")
if actuate is None:
return self.__relays[relay].value()
self.__relays[relay].value(actuate)
def actuate_relay(self, relay):
if relay < 0 or relay > NUM_RELAYS:
raise ValueError("relay out of range. Expected RELAY_1 (0), RELAY_2 (1), or RELAY_3 (2)")
self.__relays[relay].on()
def release_relay(self, relay):
if relay < 0 or relay > NUM_RELAYS:
raise ValueError("relay out of range. Expected RELAY_1 (0), RELAY_2 (1), or RELAY_3 (2)")
self.__relays[relay].off()
def output(self, output, value=None):
if output < 0 or output > NUM_OUTPUTS:
raise ValueError("output out of range. Expected OUTPUT_1 (0), OUTPUT_2 (1), or OUTPUT_3 (2)")
if value is None:
return self.__outputs[output].value()
self.__outputs[output].value(value)
def read_input(self, input):
if input < 0 or input > NUM_INPUTS:
raise ValueError("input out of range. Expected INPUT_1 (0), INPUT_2 (1), INPUT_3 (2), or INPUT_4 (3)")
return self.__inputs[input].value()
def read_adc(self, adc):
if adc < 0 or adc > NUM_ADCS:
raise ValueError("adc out of range. Expected ADC_1 (0), ADC_2 (1), or ADC_3 (2)")
voltage = self.__analogs[adc].read_voltage()
gamma = 2.8
value = int(pow(voltage / self.MAX_ADC_LED_VOLTAGE, gamma) * 65535 + 0.5)
self.__adc_led_pwms[adc].duty_u16(value)
return voltage
def reset(self):
# Reset the relays
for i in range(NUM_RELAYS):
self.release_relay(i)
# Reset the outputs
for i in range(NUM_OUTPUTS):
self.output(i, False)
# Reset the adc LEDs
for i in range(NUM_ADCS):
self.__adc_led_pwms[i].duty_u16(0)
# Reset the switch LEDs
for i in range(NUM_SWITCHES):
self.__switch_led_pwms[i].duty_u16(0)
# Reset the connectivity LED
self.__conn_led_pwm.duty_u16(0)