mChumby – Mazda/Madox Chumby

It’s taken me a while to officially start this project.  When I first bought my Mazda 3 I had envisaged making my own speedometer based off the Mazda CAN Bus but somehow never quite got around to it.

I even ended up buying 2 Chumbies for the purpose of hacking one and developing the same speedo (The chumby is such a great alarm clock I couldn’t live without one…).

There has been quite a bit of interest in the comments for source code/information etc etc.  So now I’m officially starting the mChumby project!  This first post is basically a brainstorming session write-up or a mini requirements specification on myself.  Feel free to comment on any ideas/improvements you think I can make.

(This post seems too wordy without a photo but I’m just too lazy)

The concept

A Chumby will connect via CAN Bus to the Mazda to offer an alternative ‘GUI’ to the car.  Information such as fuel consumption that has been removed from the Australian Mazda’s will be displayed.

Since a chumby doesn’t have native CAN Bus connections, a custom daughter board with dual CAN controllers and transceivers will be built to replace the native Chumby power board.

The hardware

In addition to the Chumby mainboard, there will be a custom daughter board to be made to handle the car interface.  The Chumby has multiple SPI interfaces brought out through the ‘Chumbilical’, as well as on-board voltage regulators that will take up to 15V.  So a quick brainstorm on the daughter-board components leads me to :-

CAN Controller : MCP2515 – Has SPI interface, great for Chumby.
CAN Transceiver : TJA1041 or whatever it is I have in my box of electronics – Because I have them already
USB Connectors + Associated electronics…
Automotive Voltage Suppressor : Vishay had a few good ones

Luxuries like accelerometers are too much of a pain to hand solder 🙂

The software

I’m going to try use completely open source software in the development.  This will be discounting the Flash Lite 3 player that ships with the Chumby.  I debated much about developing a QT app or a flash widget, what I decided was undecided and I switched back and forth.  In the end, I’m sticking with Flash (for now).

There are two main pieces of software required, the GUI and the CAN Bus drivers.

The GUI as decided before will be Flash targetting the Flash Lite 3 on the Chumby.  For this I decided to use HaXe, which will happily compile to Flash 8 bytecode.  It is not as popular in open source flash developement as say ActionScript 2 with mtasc but I figured I’ll use the newer language.  Unfortunately there is a severe lack of HaXe examples on the net and when you find them, you’ll find that its based on Flash 9 API… GAH.  However a little bit of experimentation and googling around made me see how easy it is to actually use HaXe.  More on this later.

The driver’s for the MCP2515’s I haven’t really looked at yet but I hope that it’ll be a simple matter of adapting MCP2515 code from elsewhere and merging it with hopefully some SPI driver’s in the Chumby kernel source (did I mention how great the Chumby is? Source code is made available!).

There is a bit of other software that’ll be used to create this project.  I’m planning on learning how to use KiCAD to generate the PCB where as I’ve only previously used Eagle on my hobby projects.  While I’m sure Eagle will get the job done, I really want to give a try in learning how to use the open source KiCAD.  Let me know if you have any hints.

Geany will be my lightweight editor/IDE of choice, its so simple to use and amazing.  (I like Notepad++ in Windows but I haven’t booted Windows at home for a while…)

The HMI

I like easy to use and simple user interfaces.  This is especially true when I’m driving, I definitely do not want this thing distracting me.  My initial idea was to organise it such that all the ‘buttons’ are on the corners of the screen but on second thought even trying to touch that while driving may be a bit difficult.

Current idea is to use some simple swipe gestures to control the screen.  The idea is to have minimal interaction with my mChumby as possible while driving.  I intend to have 2 screens, one to display a large speedo and the main displays and a second screen to display a smaller speed with alot of additional potentially useless information (I haven’t figured out what yet).  I will also need brightness control to avoid getting a super bright screen at night.  So simply, swipe left-right will allow me to change screens and wipe up-down will allow me to adjust backlight brightness.

Below is just an embarassing sample of the HaXe code I was experimenting with…

Mchumby.hx

//MChumby GUI - HaXe code targetting Flash 8

class Mchumby{
  //Gesture Variables
  static var fGestureStartX:Float;
  static var fGestureStartY:Float;
  static var fGestureEndX:Float;
  static var fGestureEndY:Float;
  static var fGestureDeltaX:Float;
  static var fGestureDeltaY:Float;

  //MovieClips (Screens)
  static var mcMain : flash.MovieClip;

  static var mcD100 : flash.MovieClip;
  static var mcD101 : flash.MovieClip;
  //MovieClips (Buttons/Other Elements)

  //Text Fields
  static var tfText : flash.TextField;

  static var tfSpeedo : flash.TextField;
  static var tfAccelX : flash.TextField;
  static var tfAccelY : flash.TextField;
  static var tfAccelZ : flash.TextField;  

  //Text Format/Styles
  static var ts = new flash.TextFormat();
  static var tsCenter = new flash.TextFormat();

  public function new(){
    //Constructor - Most items are moved to main();
    fGestureStartX=0;
    fGestureStartY=0;
  }

  static function main(){
    //Setup main MovieClip
    mcMain = flash.Lib.current;

    //Set up some font styles
    ts.font = "Arial";
    ts.size = 24;
    ts.color = 0x00FFFF;

    tsCenter.font = "Arial";
    tsCenter.size = 24;
    tsCenter.color = 0xFF0000;
    tsCenter.align = 'center';

    //Set up screens the new way
    //var m100 = new M100(mcMain);
    //var m101 = new M101(mcMain);

    //Set up screens
    mcD100 = mcMain.createEmptyMovieClip("D100", mcMain.getNextHighestDepth());
    mcD101 = mcMain.createEmptyMovieClip("D101", mcMain.getNextHighestDepth());

    //Set up text fields
    tfText = mcMain.createTextField("tfText", mcMain.getNextHighestDepth(), 20, 20, 280, 100);
    tfText.setNewTextFormat(tsCenter);

    //Set up text fields (D100)
    tfSpeedo = mcD100.createTextField("speedotext", mcD100.getNextHighestDepth(), 20,50,280,100);
    tfSpeedo.setNewTextFormat(ts);
    tfAccelX = mcD100.createTextField("accelx", mcD100.getNextHighestDepth(), 20,80,280,100);
    tfAccelX.setNewTextFormat(ts);
    tfAccelY = mcD100.createTextField("accely", mcD100.getNextHighestDepth(), 20,110,280,100);
    tfAccelY.setNewTextFormat(ts);
    tfAccelZ = mcD100.createTextField("accelz", mcD100.getNextHighestDepth(), 20,140,280,100);
    tfAccelZ.setNewTextFormat(ts);

    //Set up text fields (D101)

    //Initialise text
    tfText.text = 'Hello World!';

    tfSpeedo.text = 'Accelerometer Values...';

    //Set up event handlers
    mcMain.onMouseDown = startGesture;
    mcMain.onMouseUp = endGesture;
    mcMain.onEnterFrame = update;
  }

  static function update(){
    tfAccelX.text = Std.string(ChumbyNative.getAccelerometer(5));
    tfAccelY.text = Std.string(ChumbyNative.getAccelerometer(6));
    tfAccelZ.text = Std.string(ChumbyNative.getAccelerometer(7));
  }
  static function startGesture () {
    fGestureStartX = flash.Lib.current._xmouse;
    fGestureStartY = flash.Lib.current._ymouse;
  }

  static function endGesture () {
    fGestureEndX = flash.Lib.current._xmouse;
    fGestureEndY = flash.Lib.current._ymouse;
    fGestureDeltaX = Math.round(fGestureEndX - fGestureStartX);
    fGestureDeltaY = Math.round(fGestureEndY - fGestureStartY);

		//Rather than else-if, the following if's are deliberately done to allow compound gestures
		//e.g. Up & Left, Down & Right etc.
    if (!Math.isNaN(fGestureDeltaY) && (fGestureDeltaY > 100)) {
      gestureDown();
    }

    if (!Math.isNaN(fGestureDeltaY) && (fGestureDeltaY < -100)) {
      gestureUp();
    } 

    if (!Math.isNaN(fGestureDeltaX) && (fGestureDeltaX < -200)) {
      gestureLeft();
    }

    if (!Math.isNaN(fGestureDeltaX) && (fGestureDeltaX > 200)) {
      gestureRight();
    }
  }
  static function gestureRight () {
    tfText.text = "To the right!";
    mcD100._alpha = 0;
    //tfText.setTextFormat(ts);
  }
  static function gestureLeft () {
    tfText.text = "To the left!";
    mcD100._alpha = 100;
  }
  static function gestureUp () {
    tfText.text = "Bright!";
    ChumbyNative.setLCDMute(0);
  }
  static function gestureDown () {
    tfText.text = "Dim!";
    ChumbyNative.setLCDMute(1);
  }
}

ChumbyNative.hx

class ChumbyNative{
  public static function getLCDMute():Int{
    return flash.Lib._global.ASnative(5,19);
  }
  public static function setLCDMute(x:Int):Void{
    flash.Lib._global.ASnative(5,20)(x);
  }
  public static function getAccelerometer(x:Int):Float{
    return flash.Lib._global.ASnative(5,60)(x);
  }
}

Mchumby.hxml

-swf mchumby.swf
-main Mchumby
-swf-header 320:240:12:000033
-swf-version 8

3 thoughts on “mChumby – Mazda/Madox Chumby”

  1. I’ve realised the error of my ways!
    Death to the static hack 🙂 All “static” except …

    static function main(){
    new Mchumby();
    }

    and all the initialisation code correctly moved to the ‘new()’ constructor!

    Learning is a great experience.

  2. Hi, great site with lots of great ideas, I’m the proud owner of a Mazda6 and on this one we have a wire labelled TNS+ that travels between all dashboard components, and it is supposed to be a PWM output for dashboard brightness control.

    Just an idea, but maybe you can hook up to this for controlling the brightness of your screens, cause I think it should be there on a Mazda3 as well.

    😉

Leave a Reply

Your email address will not be published. Required fields are marked *