element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet & Tria Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • About Us
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      • Japan
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Vietnam
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Upcycle It
  • Challenges & Projects
  • Design Challenges
  • Upcycle It
  • More
  • Cancel
Upcycle It
Blog [Upcycle It] Interactive Race Car Driver - Controlling the Furby
  • Blog
  • Forum
  • Documents
  • Polls
  • Files
  • Events
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: Workshopshed
  • Date Created: 24 May 2017 9:27 PM Date Created
  • Views 1385 views
  • Likes 7 likes
  • Comments 8 comments
  • upcycled_interactiveracecardriver
Related
Recommended

[Upcycle It] Interactive Race Car Driver - Controlling the Furby

Workshopshed
Workshopshed
24 May 2017

In the previous post, I looked at Hooking up the Furby to the Edison. Now to put that together with some software so we can control what the Furby does.

 

Motor

Driving the motor from the H-Bridge board is pretty much the same as per  [Upcycle It] Interactive Race Car Driver - Powering Motors although there are the extra transistor level shifters to factor in. This means all of the signals are inverted.

 

imageimage

MCU

As I discovered that the rate of pulses from the optical sensor is quite high, I decided that the MCU capability of the Edison would be ideal to monitor the inputs. Then a Node program can be used to get the current value of the counter from the MCU. So that the MCU knows which direction that the Furby's cam wheel is rotating a simple message can be sent over the serial communications channel.

image

Installing the MCU SDK

Installation of the SDK is straightforward, it's an Eclipse-based application so to get that to work on Windows there are quite a few extra components to install such as JRE and Cygwin.

 

I did have a few issues creating projects and this seemed partly due to my Workspace folder and partly because of my installation.

 

Ensure you:

  • Keep paths short
  • Keep paths without spaces in them
  • Install all of the components
  • Set the Environment variable

 

Installing the MCU SDK

 

Target IP

Unlike a lot of embedded SDKs the MCU SDK uploads the code over the network. So before you can upload your project you need to set the TARGET_IP. So I set that to the name of the board and it worked just fine.

image

For .local addresses to work on Windows, you might need to install a service such as Bonjour

 

https://learn.adafruit.com/bonjour-zeroconf-networking-for-windows-and-linux/overview

Sample Scripts

There are some tools that can help to configure the ports, it's worth downloading these as unlike things like MRAA, the MCU code "gpio_setup" does not actually configure the hardware to be an input or output.

 

Sample scripts for the MCU SDK

 

I installed the init_DIG script as follows:

 

mkdir tools
cd tools
wget http://downloadmirror.intel.com/24910/eng/init_DIG.sh
chmod +x init_DIG.sh
cd ..

 

Then configured a couple of the pins with:

 

./tools/init_DIG.sh -o 7 -d input
./tools/init_DIG.sh -o 8 -d input

 

This article Using an mcu on the intel edison board with the ultrasonic range sensor confirms that you need to do this each time the Edison boots. I'm also wondering if I can use MRAA to configure the ports in the control code for the Furby.

 

Testing

For initial testing, I used the grove shield, a switch for counting and capacitive sensor for reset.

 

The MCU application detects the signals with the aid of two interrupt handlers.

gpio_register_interrupt

Register an interrupt handler for one GPIO port.

int gpio_register_interrupt(int gpio, int mode, irq_handler_t isr);

...where:

  • gpio: GPIO port number
  • mode: 0 = falling edge interrupt, 1 = rising edge interrupt
  • isr: interrupt handler function
  • Return value: 0 if successful

The status is reported via the debug port and the current count can be received via the host to mcu serial port /dev/ttymcu0. I limited the counts to 50 for this initial testing to check it wrapped around correctly.

 

MCU Test code

#include "mcu_api.h"
#include "mcu_errno.h"
volatile int counter;
volatile int direction;
int maxPulses;
 int IRQpulse(int req)
 {
   counter += direction;
   if (counter < 0) {
    counter = maxPulses;
   }
   if (counter > maxPulses) {
    counter = 0;
   }
   debug_print(DBG_INFO, "Counter: %d\n",counter);
   return IRQ_HANDLED;
 }
 int IRQreset(int req)
 {
   counter = 0;
   debug_print(DBG_INFO, "Reset.\n");
   return IRQ_HANDLED;
 }
 void mcu_main()
 {
 char buf[64];
 char response[20];
    int retCode;
    int len;
    debug_print(DBG_INFO, "mcu app starting...\n");
    direction = 1;
    maxPulses = 50;    //Max pulses per revolution (need to find this experimentally)
    gpio_setup(48, 0);  /* set GPIO 48 DIG7 as input*/
    gpio_register_interrupt(48, 1, IRQpulse);
    gpio_setup(49, 0);  /* set GPIO 49 DIG8 as input*/
    gpio_register_interrupt(49, 1, IRQreset);
    while (1)
    {
     //Wait for command from host
     do {
      retCode = host_receive((unsigned char *)buf, 64);
         mcu_sleep(10);
     } while (retCode <= 0);
     switch(buf[0]) {
        case 'C'  :
         debug_print(DBG_INFO, "Counter: %d\n", counter);
         debug_print(DBG_INFO, "Direction: %d\n", direction);
         len = mcu_snprintf(response, 20, "C%d\n", counter);
         host_send((unsigned char*)response, len);
            break;
        case 'U'  :
        debug_print(DBG_INFO, "Up\n");
        direction = 1;
           break;
        case 'D'  :
        debug_print(DBG_INFO, "Down\n");
        direction = -1;
           break;
     }
    }
 }

 

I could not get Eclipse to display the debug log but from a console I could display it with:

 

cat /dev/ttymcu1 &

 

To interact with the MCU I used the 3 letters, C to display counter, D to count down and U to count up.

 

echo C > /dev/ttymcu0
echo D > /dev/ttymcu0
echo U > /dev/ttymcu0

 

image

The reset and pulse counters proved to work correctly. There are reports of the MCU not being able to cope with very high pulse rates. If this is the case I'll drop the debug statements and change the speed of the motor until it works reliably.

 

Monitoring the position

Once I was happy the MCU was working as expected I hooked the inputs upto the Furby. So that I could move both forward and backwards I needed to know the maximum number of pulses. To find this, I set the max in code to a large number and planned span the motor by hand.

 

Initially when I set this up the reset line was going wild. I used a resistor to pull that high and confirmed it worked by manually closing the contacts.

I manually span the slotted disk and after a short delay I got a reading of 209 pulses. Note to self, that needs to go to 1.8v when it's wired up to the mini-breakout.

 

I repeated this experiment with the motor driven from a battery and there was a debounce problem where I was getting multiple resets. Given that it was a mechanical spring contact this is not surprising. I added a simple delay into the reset interrupt handler and that improved the problem but did not completely eliminate the problem with a "bounce" appearing 7 or so pulses later. I'll likely use a mechanism where the reset initialtes a countdown and can't be retriggered until 10 or more pulses have been detected.

image

These experiments did provide repeated results of 208 pulses per revolution. I added that into the code and also added a call via the host API to return this max value. This experiment also demonstrated that the MCU was happily counting pulses and not obviously skipping.

 

Latest MCU code

#include "mcu_api.h"
#include "mcu_errno.h"
volatile int counter;
volatile int direction;
int maxPulses;
 int IRQpulse(int req)
 {
   counter += direction;
   if (counter < 0) {
    counter = maxPulses;
   }
   if (counter > maxPulses) {
    counter = 0;
   }
   debug_print(DBG_INFO, "Counter: %d\n",counter);
   return IRQ_HANDLED;
 }
 int IRQreset(int req)
 {
   counter = 0;
   mcu_sleep(20);  //Debounce
   debug_print(DBG_INFO, "Reset.\n");
   return IRQ_HANDLED;
 }
 void mcu_main()
 {
 char buf[64];
 char response[20];
    int retCode;
    int len;
    debug_print(DBG_INFO, "mcu app starting...\n");
    direction = 1;
    maxPulses = 208;    //Max pulses per revolution, was determined experimentally
    gpio_setup(48, 0);  /* set GPIO 48 DIG7 as input*/
    gpio_register_interrupt(48, 1, IRQpulse);
    gpio_setup(49, 0);  /* set GPIO 49 DIG8 as input*/
    gpio_register_interrupt(49, 1, IRQreset);
    while (1)
    {
     //Wait for command from host
     do {
      retCode = host_receive((unsigned char *)buf, 64);
         mcu_sleep(10);
     } while (retCode <= 0);
     switch(buf[0]) {
        case 'C'  :
         debug_print(DBG_INFO, "Counter: %d\n", counter);
         debug_print(DBG_INFO, "Direction: %d\n", direction);
         len = mcu_snprintf(response, 20, "C%d\n", counter);
         host_send((unsigned char*)response, len);
            break;
        case 'M'  :
         debug_print(DBG_INFO, "Max: %d\n", maxPulses);
         len = mcu_snprintf(response, 20, "M%d\n", maxPulses);
         host_send((unsigned char*)response, len);
            break;
        case 'U'  :
        debug_print(DBG_INFO, "Up\n");
        direction = 1;
           break;
        case 'D'  :
        debug_print(DBG_INFO, "Down\n");
        direction = -1;
           break;
     }
    }
 }

 

What next?

Test the H-Bridge with the mini-breakout and level shifters

Test the Sensors with the mini-breakout and level shifters

Write some high-level control code that communicates with the MCU and uses the counts from the Northwestern team to drive specific motions e.g. talking, ears waggling.

 

Reference

Installing the MCU SDK

Registering_an_interrupt_handler_to_a_GPIO_port

MCU API

Using an mcu on the intel edison board with the ultrasonic range sensor

Sample scripts for the MCU SDK

MCU interrupt performance

 

Previous Posts

Upcycle It Blogs tagged with upcycled_interactiveracecardriver

  • Sign in to reply

Top Comments

  • gpolder
    gpolder over 8 years ago +2
    nice update, thanks for explaining how to use the MCU.
  • Workshopshed
    Workshopshed over 8 years ago in reply to jasonwier92 +2
    Multiple events is why I dropped the delay approach. The frequency of events is slow enough for me to see in the console when the motor is turning at full speed. Let's say it's counting backwards and its…
  • jasonwier92
    jasonwier92 over 8 years ago +1
    How does your debouncing effect the counting frequency? OR what if the sensor gets two inputs, while you are still debouncing? Just to second what Gerrit Polder said, thank you for showing the MCU code…
  • Workshopshed
    Workshopshed over 8 years ago in reply to mcb1

    A hall effect switch could work but is likely overkill. The Furby's movement does not need to be an exact one so even without debouncing the contacts +-7 pulses would be fine.

     

    The original designers were brilliant and likely working within tight price constraints hence why all the switches are just springy bits of metal.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • mcb1
    mcb1 over 8 years ago

    I presume you can't add a small magnet and a Hall effect for the reset and detection.?

     

    Looks like the original desgners were extremely clever.

     

     

     

    Mark

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • DAB
    DAB over 8 years ago

    Nice update Andy,

     

    Good description of your approach and your reasoning.

     

    DAB

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Workshopshed
    Workshopshed over 8 years ago in reply to jasonwier92

    Multiple events is why I dropped the delay approach. The frequency of events is slow enough for me to see in the console when the motor is turning at full speed.

     

    Let's say it's counting backwards and its slightly out of sync so the reset does not align with zero.

     

    So it counts down 10,9,8,7,6 then gets a reset.

    It will continue counting at 0,208,207,206 at this point there might be another reset but it would be ignored

    So it would continue counting down from 205,204,203,202,201,200,199

    At this point the reset lock would be cleared but also the cam would be well away from the home sensor and hence we should not get any resets until it completes a full cycle.

     

    So some of the counts could be different durations but this should not really affect the motion as I don't need to get to a precise point on the cycle.

     

    My plan for the control algorithm will be to tell it to rotate to a specific point but allow for the fact it might go past that point.

     

    30 to 60

    ears down, eyes open, mouth open, not tilted

    60 to 100

    ears down, eyes open, mouth shut, not tilted

     

    So to make it talk, I might cycle it between 45 and 75, if it overshoots and runs from 42 to 78 that should not matter.

     

    Potentially there is a problem with trying to get to the small numbers e.g. 1-7, 201-208 where it might end up hunting back and forth. So I'll avoid using those values.

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • jasonwier92
    jasonwier92 over 8 years ago

    How does your debouncing effect the counting frequency?  OR what if the sensor gets two inputs, while you are still debouncing?

     

    Just to second what Gerrit Polder said, thank you for showing the MCU code. 

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
>
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2026 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube