Can’t get the callback buried in Jaws class to work.
[Note the IOExtender class controlling an MCP23008 I2C I/O Extender and BlinkM code removed for brevity.]
Circuit consists of a wtv020m01 Sound playback module controlled by the Voice class.
A servo is controlled by the Jaws class. The eventual goal is to have the servo sweep when it sees the busy (playing a sound) signal of the sound module.
What works:
Servo by itself can be positioned at will via the agent.
Sound module works and using an LED I can see the busy signal go high and low.
What doesn’t work:
Feeding the busy signal to the pin
Putting a high signal on the pin I use for detecting the busy signal.
I see the high signal at the pin measured with a multimeter
What I have tried in the code:
Moving the pin around - look for the “earPin” variable
Changing DIGITAL_IN to DIGITAL_IN_PULLDOWN
What I observed which is weird:
After downlading new code, it appears the lipSync call back is called. I never see any other debug from that callback again:
2014-06-08 17:55:09 UTC-4 [Status] Device booting; 17.39% program storage used ...SNIP... 2014-06-08 17:55:11 UTC-4 [Device] Lip Syncing 0 2014-06-08 17:55:20 UTC-4 [Device] Servo Position: 0.11375 2014-06-08 17:55:33 UTC-4 [Device] Servo Position: 0.04 2014-06-08 17:56:01 UTC-4 [Device] Sound Command Sent 13 2014-06-08 17:56:01 UTC-4 [Device] Sync Played Voice 13 2014-06-08 17:56:37 UTC-4 [Device] Servo Position: 0.091625 2014-06-08 17:56:53 UTC-4 [Device] Sound Command Sent 13 2014-06-08 17:56:55 UTC-4 [Device] Sync Played Voice 13 2014-06-08 17:56:55 UTC-4 [Device] Servo Position: 0.091625
`
// Class for the sound board.
class Voice {
_clockPin = null
_dataPin = null
_resetPin = null
constructor(clockPin, dataPin, resetPin) {
_clockPin = clockPin
_clockPin.configure(DIGITAL_OUT)
_clockPin.write(1); // Initialize clock high to avoid false reading data
_dataPin = dataPin
_dataPin.configure(DIGITAL_OUT)
_resetPin = resetPin
_resetPin.configure(DIGITAL_OUT)
}
// SOUNDCARD Related Controls
function reset() {
server.log(“Reset Sound”)
_resetPin.write(1)
imp.sleep(0.100) // Pulse the Reset Pin for 100 ms
_resetPin.write(0)
}
function playVoice(voiceNumber) {
sendCommand(voiceNumber)
server.log("Sync Played Voice " + voiceNumber)
}
function asyncPlayVoice(voiceNumber){
server.log("Async Playing Voice " + voiceNumber)
}
function stopVoice(){
sendCommand(STOP)
server.log(“Stopped Voice”)
}
function pauseVoice(){
sendCommand(PLAY_PAUSE)
server.log(“Paused Voice”)
}
function mute(){
sendCommand(VOLUME_MIN)
server.log(“Muted Voice”)
}
function unmute(){
sendCommand(VOLUME_MAX)
server.log(“Unmuted Voice”)
}
// The guts of the interface is the timing related to sending
// the voice or special case command
function sendCommand(command){
local iCommand = command.tointeger()
//Start bit Low level pulse.
_clockPin.write(0);
imp.sleep(0.020); // 20 milli seconds
for (local mask = 0x8000; mask > 0; mask = mask >> 1) {
//Clock low level pulse.
_clockPin.write(0)
imp.sleep(0.000050) // 50 micro seconds
//Write data setup.
if (iCommand & mask) {
_dataPin.write(1)
}
else {
_dataPin.write(0)
}
//Write data hold.
imp.sleep(0.000050) // 50 micro seconds
//Clock high level pulse.
_clockPin.write(1)
imp.sleep(0.000100) // 100 micro seconds
if (mask>0x0001){
//Stop bit high level pulse.
imp.sleep(0.002) // 2 milli seconds
}
}
//Busy active high from last data bit latch.
imp.sleep(0.020) // 20 milli seconds
server.log("Sound Command Sent " + command);
}
}
// Class for the servo motor
class Jaws {
_mouthPin = null // Controls the Server
_earPin = null // Listens for when sounds is being generated
_position = 20
_resetPin = null
_clockPin = null
_dataPin = null
constructor(mouthPin, earPin) {
_mouthPin = mouthPin
_mouthPin.configure(PWM_OUT, 0.02, SERVO_MIN)
_earPin = earPin
_earPin.configure(DIGITAL_IN, this.lipSync())
}
//SERVO Related Commands
// Servo position function that expects a value between 0 and 100
function SetServoPercent(value) {
local scaledValue = ((value.tofloat() / 100.0) * (SERVO_MAX-SERVO_MIN)) + SERVO_MIN
_mouthPin.write(scaledValue)
server.log("Servo Position: " + scaledValue)
}
// Sweep the servo back and forward until the fat monkey stops singing
function lipSync() {
local busyState = _earPin.read()
server.log("Lip Syncing "+busyState)
while ( busyState == 1) {
// Invert the position
_position = 100.0 - _position
SetServoPercent(_position)
// Wait:
imp.sleep(0.5)
busyState = _earPin.read()
server.log("Lip cycle "+busyState)
}
}
}
// Class for BlinkM I2C RGB Device control
class BlinkM {
// Snipped//
}
// Configure i2c bus that will control the BlinkM RGB LED
hardware.i2c89.configure(CLOCK_SPEED_100_KHZ)
// Create BlinkM object using I2C communications and the BlinkM bus address
blinkM <- BlinkM(hardware.i2c89, 0x09)
// Create i/o port instances (note: each device on the same bus should have a different device address)
IOExtender <- MCP23008(hardware.i2c89, 0) // pinstrapped to device address 0
// Create the output address for the cymbols motor
cymbals <- IOExtender.pin5
cymbals.configure(DIGITAL_OUT)
// Create the addresses used by the sound board
clockPin <- hardware.pin2
dataPin <- hardware.pin5
resetPin <- IOExtender.pin4
monkeyVoice <- Voice(clockPin,dataPin,resetPin)
// Create the addresses used by the servo
mouthPin <- hardware.pin1
earPin <- hardware.pin7
monkeyMouth <- Jaws(mouthPin, earPin)
// Function to turn on the ChaosMonkey for a period of seconds
function BangCymbols(chaosTime) {
server.log(“Create chaos for: " + chaosTime + " seconds”)
cymbals.write(1)
imp.sleep(chaosTime)
cymbals.write(0)
}
// Function to play a voice on the sound board
function Play(voiceNumber) {
monkeyVoice.playVoice(voiceNumber);
}
// Function to set the color of the ChaosMonkey’s rear end
function SetColor(colorString) {
blinkM.set(colorString)
}
// Servo position function that expects a value between 0 and 100
function SetServoPercent(value) {
monkeyMouth.SetServoPercent(value)
}
// Register a handler for messages from the agent.
agent.on(“color”, SetColor)
agent.on(“chaosTime”, BangCymbols)
agent.on(“mouth”, SetServoPercent)
agent.on(“play”,Play)
`