-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from xtruan/develop
Develop
- Loading branch information
Showing
8 changed files
with
243 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
#include <MeccaBrain.h> | ||
#include <Wire.h> | ||
|
||
#ifndef cbi | ||
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) | ||
#endif | ||
|
||
// set I2C address | ||
const int I2C_ADDR = 0x8; | ||
|
||
// configure pin addresses | ||
const int LED_PIN = LED_BUILTIN; | ||
const int MECC_LED_PIN = 3; | ||
|
||
// initialize MeccaBrain | ||
MeccaBrain meccLedChain(MECC_LED_PIN); | ||
const int MECC_COMM_LOOPS = 20; | ||
|
||
// the setup function runs once when you press reset or power the board | ||
void setup() { | ||
// initialize digital pin LED_BUILTIN as an output. | ||
pinMode(LED_PIN, OUTPUT); | ||
digitalWrite(LED_PIN, LOW); | ||
|
||
// initialize Meccano LED pin as an output | ||
pinMode(MECC_LED_PIN, OUTPUT); | ||
|
||
Wire.begin(I2C_ADDR); | ||
|
||
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__) | ||
// deactivate internal pull-ups for twi | ||
// as per note from atmega8 manual pg167 | ||
cbi(PORTC, 4); | ||
cbi(PORTC, 5); | ||
#else | ||
// deactivate internal pull-ups for twi | ||
// as per note from atmega128 manual pg204 | ||
cbi(PORTD, 0); | ||
cbi(PORTD, 1); | ||
#endif | ||
|
||
Wire.onReceive(receiveEvent); // register event handler | ||
|
||
Serial.begin(9600); | ||
|
||
// discover Meccano modules | ||
for (int i = 0; i < MECC_COMM_LOOPS; i++) | ||
{ | ||
meccLedChain.communicate(); | ||
} | ||
|
||
delay(2000); | ||
} | ||
|
||
// the loop function runs over and over again forever | ||
void loop() { | ||
// NOP | ||
} | ||
|
||
// action received for Meccano LED | ||
void actionMeccLed(int setting) { | ||
byte red, green, blue; | ||
byte fadeTime = 0x0; | ||
if (setting == 0) { | ||
red = 0x0; green = 0x0; blue = 0x0; | ||
} else if (setting == 1) { | ||
red = 0x7; green = 0x0; blue = 0x0; | ||
} else if (setting == 2) { | ||
red = 0x0; green = 0x7; blue = 0x0; | ||
} else if (setting == 3) { | ||
red = 0x0; green = 0x0; blue = 0x7; | ||
} else if (setting == 4) { | ||
red = 0x7; green = 0x7; blue = 0x0; | ||
} else if (setting == 5) { | ||
red = 0x0; green = 0x7; blue = 0x7; | ||
} else if (setting == 6) { | ||
red = 0x7; green = 0x0; blue = 0x7; | ||
} else if (setting == 7) { | ||
red = 0x7; green = 0x7; blue = 0x7; | ||
} else { | ||
red = 0x0; green = 0x0; blue = 0x0; | ||
} | ||
setMeccLedColor(red, green, blue, fadeTime); | ||
} | ||
|
||
// set the color of Meccano LED. | ||
// red, green and blue are from 0 to 7 (0 - no color, 7 - max color) | ||
// fadeTime is from 0 to 7 and means the speed of color change (0 - immediate change, 7 - longest change) | ||
// example: setMeccLedColor(7, 0, 0, 0) means change color to red immediately | ||
void setMeccLedColor(byte red, byte green, byte blue, byte fadeTime) | ||
{ | ||
meccLedChain.setLEDColor(red, green, blue, fadeTime); | ||
for (int i = 0; i < MECC_COMM_LOOPS; i++) | ||
{ | ||
meccLedChain.communicate(); | ||
} | ||
} | ||
|
||
// action received for test (internal Ardino) LED | ||
void actionTestLed(char setting) { | ||
if (setting == 0) { | ||
digitalWrite(LED_PIN, 0); | ||
} else { | ||
digitalWrite(LED_PIN, 1); | ||
} | ||
} | ||
|
||
// process received event | ||
void processEvent(char type, char id, char setting) { | ||
if (type == 'L') { | ||
actionTestLed(setting); | ||
} else if (type == 'M') { | ||
actionMeccLed(setting); | ||
} else if (type == 'S') { | ||
// NOP | ||
} | ||
} | ||
|
||
// executes when data is received from I2C master | ||
// registered as an event handler; see setup() | ||
void receiveEvent(int howMany) { | ||
while (Wire.available()) { // loop through all but the last | ||
if (Wire.available() == 3) { | ||
char type = Wire.read(); // receive byte as a character | ||
char id = Wire.read(); // receive byte as a character | ||
char setting = Wire.read(); // receive byte as a character | ||
processEvent(type, id, setting); | ||
} else { | ||
char c = Wire.read(); // receive byte as a character | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
from collections import deque | ||
import csv | ||
import argparse | ||
import time | ||
|
||
import utils.transform as transform | ||
import utils.i2c as i2c | ||
from objects.anim_action import AnimAction | ||
|
||
COL_TIME_STR = 0 | ||
COL_DEVICE_TYPE = 1 | ||
COL_DEVICE_ID = 2 | ||
COL_SETTING = 3 | ||
|
||
anim_actions = deque([]) | ||
|
||
def read_anim_csv(filename, delimiter=',', quotechar='"'): | ||
csv_file = open(filename, 'r') | ||
csv_reader = csv.reader(csv_file, delimiter=delimiter, quotechar=quotechar) | ||
|
||
for row in csv_reader: | ||
time_str = str(row[COL_TIME_STR]) | ||
time_sec = transform.time_convert(time_str) | ||
device_type = str(row[COL_DEVICE_TYPE]) | ||
device_id = int(row[COL_DEVICE_ID]) | ||
setting = int(row[COL_SETTING]) | ||
|
||
action = AnimAction(time_str, time_sec, device_type, device_id, setting) | ||
anim_actions.append(action) | ||
|
||
csv_file.close() | ||
|
||
def handle_anim(): | ||
start = time.time() | ||
end = time.time() | ||
while len(anim_actions) > 0: | ||
if anim_actions[0].time_sec <= end - start: | ||
handle_action(anim_actions.popleft()) | ||
time.sleep(0.001) | ||
end = time.time() | ||
|
||
def handle_action(action): | ||
i2c.write_anim_i2c(action) | ||
print(action) | ||
|
||
def main(): | ||
parser = argparse.ArgumentParser(description="Animatronic Control Program") | ||
parser.add_argument('-i', '--input', type=str, required=True) | ||
args = parser.parse_args() | ||
|
||
input_file = args.input | ||
print('Input file: ' + input_file) | ||
if '.csv' in input_file.lower(): | ||
print('Loading file...') | ||
read_anim_csv(input_file) | ||
print('Loaded!') | ||
wait = input('Press enter to continue...') | ||
handle_anim() | ||
else: | ||
raise Exception('Invalid file type') | ||
|
||
if __name__ == '__main__': | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
|
||
class AnimAction: | ||
def __init__(self, time_str, time_sec, device_type, device_id, setting): | ||
self.time_str = time_str | ||
self.time_sec = time_sec | ||
self.device_type = device_type | ||
self.device_id = device_id | ||
self.setting = setting | ||
|
||
def __str__(self): | ||
return str(self.time_str) + '-' + str(self.device_type) + '-' + str(self.device_id) + '-' + str(self.setting) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
00:00:01.10,LED,1,1 | ||
00:00:01.20,LED,1,0 | ||
00:00:01.30,LED,1,1 | ||
00:00:01.40,LED,1,0 | ||
00:00:03.00,MLED,1,0 | ||
00:00:05.00,MLED,1,1 | ||
00:00:07.00,MLED,1,2 | ||
00:00:09.00,MLED,1,3 | ||
00:00:11.00,MLED,1,4 | ||
00:00:13.00,MLED,1,5 | ||
00:00:15.00,MLED,1,6 | ||
00:00:17.00,MLED,1,7 | ||
00:00:20.00,SVO,1,90 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
from smbus import SMBus | ||
|
||
from objects.anim_action import AnimAction | ||
|
||
I2C_ADDR = 0x8 # bus address | ||
I2C_BUS = SMBus(1) # indicates /dev/ic2-1 | ||
|
||
|
||
|
||
def write_anim_i2c(action): | ||
data = [action.device_type.encode()[0], action.device_id, action.setting] | ||
I2C_BUS.write_i2c_block_data(I2C_ADDR, 0x0, data) | ||
#I2C_BUS.write_byte(I2C_ADDR, action.device_type.encode()[0]) | ||
#I2C_BUS.write_byte(I2C_ADDR, action.device_id) | ||
#I2C_BUS.write_byte(I2C_ADDR, action.setting) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
|
||
def time_convert(time_str): | ||
time_list = time_str.split(':') | ||
return float(int(time_list[0]) * 3600 + int(time_list[1]) * 60 + float(time_list[2])) |