Source code, released under GPL 2
/** * Control for custom A5 electronic trigger * * Uses I2C to store settings and operate, with a switch as fallback * ATTiny45 * * * Copyright (C) 2013 Paint Race Inc. * * Author Nathan Gray * Released 2014-08-18 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ // Use i2c for commands & settings #include <TinyWireS.h> // For storing settings #include <EEPROM.h> // Default I2C Slave address #define I2C_SLAVE_ADDR 0x26 //#define I2C_SLAVE_ADDR B0100001 // i2c commands #define CMD_SET_ADDR 0x01 #define CMD_SET_ON_TIME 0x02 #define CMD_SET_OFF_TIME 0x03 #define CMD_SAFE_ON 0x0A #define CMD_SAFE_OFF 0x0B #define CMD_FIRE 0x10 // a5_a5_status #define STATUS_SAFE 0x00 #define STATUS_FIRE 0x0F // Pin definitions #define FIRE_PIN 4 #define MANUAL_PIN 3 #define INT_PIN 1 // Memory locations #define I2C_ADDR 0 #define ON_TIME_ADDR 1 #define OFF_TIME_ADDR 2 // Some safe defaults. solenoid should be good for 10% byte i2c_slave = I2C_SLAVE_ADDR; int on_time = 10; int off_time = 100; byte a5_status = STATUS_FIRE; void setup() { // Init pins pinMode(MANUAL_PIN, INPUT); digitalWrite(MANUAL_PIN, HIGH); pinMode(FIRE_PIN, OUTPUT); digitalWrite(FIRE_PIN, LOW); pinMode(INT_PIN, OUTPUT); digitalWrite(INT_PIN, HIGH); // Load settings, if there if(EEPROM.read(I2C_ADDR) != 0xFF) { i2c_slave = EEPROM.read(I2C_ADDR); on_time = EEPROM.read(ON_TIME_ADDR); // Off time should be at least 10x on time, but that could overflow a byte off_time = EEPROM.read(OFF_TIME_ADDR) * 10; } TinyWireS.begin(i2c_slave); // Wait to let the big cap charge delay(500); } void loop() { if(digitalRead(MANUAL_PIN) == LOW) { fire(); } byte byteRcvd,i = 0; int in = 0; if (TinyWireS.available() > 0){ // got I2C input! byteRcvd = TinyWireS.receive(); // get the byte from master switch(byteRcvd) { case CMD_SET_ADDR: byteRcvd = TinyWireS.receive(); if(byteRcvd >= I2C_SLAVE_ADDR && byteRcvd <= I2C_SLAVE_ADDR + 1) { EEPROM.write(I2C_ADDR, i2c_slave); TinyWireS.send(i2c_slave); // Need to reset now... } break; case CMD_SET_ON_TIME: on_time = TinyWireS.receive(); EEPROM.write(ON_TIME_ADDR, on_time); TinyWireS.send(on_time); break; case CMD_SET_OFF_TIME: in = TinyWireS.receive(); in |= (TinyWireS.receive() << 8); if(in > on_time * 100) { off_time = in; } else { off_time = on_time * 100; digitalWrite(INT_PIN, HIGH); delay(50); digitalWrite(INT_PIN, LOW); } EEPROM.write(OFF_TIME_ADDR, off_time); TinyWireS.send(off_time); break; case CMD_SAFE_OFF: a5_status = STATUS_FIRE; //blinky(3); break; case CMD_SAFE_ON: a5_status = STATUS_SAFE; break; case CMD_FIRE: fire(); break; } } digitalWrite(INT_PIN, a5_status == STATUS_SAFE ? HIGH : LOW); } // Debug void blinky(int times) { for(int i = 0; i < times * 2; i++){ digitalWrite(INT_PIN, i % 2 == 1 ? HIGH : LOW); delay(100); } } void fire() { if(a5_status == STATUS_SAFE) return; digitalWrite(FIRE_PIN, HIGH); delay(on_time); digitalWrite(FIRE_PIN, LOW); delay(off_time); }
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.