Notes About Working with Various Arduino & Netduino Microcontroller Boards

Saturday, March 9, 2013

Connecting a uM-FPU Math Co-Processor to an Arduino via I2C

Last November, I made a couple posts about using the Micromega uM-FPU (32-bit) floating point unit with an Arduino. In February I posted about using the 64-bit version with an Arduino Due via I2C (rather than SPI). This post covers using the 32-bit math co-processor (uM-FPU v3.1) with an Arduino connected via I2C.


Connections:


With notch on top of the chip pointing upward, the pins are numbered moving counterclockwise down the left side and back up the right side.

uM-FPU v3.1   Arduino Leonardo
1 (/MCLR)     5V
4 (CS)        5V
9 (SERIN)     GND 
11 (SCL)      SCL (with 4k7 pull-up resistor)
12 (SDA)      SDA (with 4k7 pull-up resistor) 
13 (VSS)      GND
14 (VDD)      5V
17 (AVSS)     GND
18 (AVDD)     5V


Code:   


The manufacturer, Micromega Corp., has good uM-FPU documentation on their site. There are also a couple code examples included with the FPU library. Note, however, that this library will not work with an I2C connections. The code below shows how to pass values and command and values to the FPU and retrieve the results.  

This example calculates the square roots of integers 2 through 32766 and displays the result in the serial console.

#include <Wire.h>

#define FPU_ADDR   0x64
#define LOADWORD   0x5B
#define FTOA       0x1F   // Convert float to ASCII
#define SELECTA    0x01   // Select register A
#define SQRT       0x41   // reg[A] = sqrt(reg[A])
#define READSTR    0xF2   // Read string from string buffer

#define SYNC       0xF0   // Get synchronization byte
#define SYNC_CHAR  0x5C   // sync character

#define RESET_REG  0x01
#define RESET_CMD  0x00
#define DATA_REG   0x00

void setup() {
  Serial.begin(115200);
  while(!Serial) { ; }
  Serial.println("START");
  Wire.begin();
  Serial.println("0");
  // Reset FPU by writing 0 to I2C register addr. 1
  Wire.beginTransmission(FPU_ADDR);
  Wire.write(RESET_REG);
  Wire.write(RESET_CMD);
  Wire.endTransmission();
  // Recommended delay after reset
  delayMicroseconds(15);
  Serial.println("1");
  // Check FPU communication
  Wire.beginTransmission(FPU_ADDR);
  Wire.write(DATA_REG);
  Wire.write(SYNC);
  Wire.endTransmission();
  delay(10);
  Wire.requestFrom(FPU_ADDR, 1);
  while(Wire.available())    
  { 
    char c = Wire.read();    
    if(!c == SYNC_CHAR) {
      Serial.println("uM-FPU not responding.");
      while(1); 
    }      
  }
}

void loop() {
  for(int i = 1; i < 32767; i++) {
    String answer = "Sqrt of ";
    (answer += i) += " is ";
    Wire.beginTransmission(FPU_ADDR);
    Wire.write(DATA_REG);
    // Use reister 0 as accumulator
    Wire.write(SELECTA);
    Wire.write(0); 
    Wire.write(LOADWORD);
    Wire.write(i >> 8);    // Load high byte
    Wire.write(i & 0xFF);  // Load low byte
    Wire.write(SQRT);
    Wire.write(FTOA);
    Wire.write(0x00);
    Wire.write(READSTR);
    Wire.endTransmission();
    Wire.requestFrom(FPU_ADDR, 8);
    while(Wire.available())    
    { 
      char c = Wire.read();    
      answer += c;         
    }
    Serial.println(answer);
  }
  delay(5000);
  Serial.println();
}

7 comments:

  1. I had the 8-pin V2 uMFPU working with a PIC microcontroller a few years ago, and being a new Arduino enthusiast and wanting to get more familiar with the Wire library I decided to try to get it working again with the UNO board. After a day or so of no joy, turned to Google and found your post. Even though your wrote it for the v3.1 chip it gave me something to compare to, and after an hour or so, I finally had mine working!

    I guess now I’ll spend a little more time with v2 – for old times sake, then move up to the 14-pin v3.1 chip.

    BTW, did you see the benchmark postings regarding the SPI library for the 3.1 uMFPU at the Arduino forum? Some of the results surprised me and I’d like to look into it a bit more.

    http://arduino.cc/forum/index.php/topic,101298

    Your blog looks interesting. I want to spend some more time here.

    ReplyDelete
    Replies
    1. Hi Blueglide -

      Thanks for your comment. I'm glad you found the post helpful. I2C definitely won't be as fast as SPI in terms of connection speed, but it is an available option (both on the 32- & 64-bit versions of the FPU).

      Delete
  2. Hello Brad!

    I'am new to the Arduino World but for a recent project i need to calculate the Julian Date very accurate.
    So i bought an uMFPU v3.1 32bit.

    Well, i dont know if iam to dumb but i think after some days of testing that the FPU chips Floating point range is not bigger than the Arduino MEGAs 2560 floating point range. Both are 32bit.

    I get an accuracy of 7 digits, no matter where the comma stands.

    I need the following format: JD 2456782.960764

    Maybe i should have bought the 64bit version?

    ReplyDelete
    Replies
    1. This comment has been removed by the author.

      Delete
    2. Hi Christian -

      My first response was that you could get more than 7 digits (I was sure I had done so), but I now think I was wrong. I need to run some tests. I can definitely get more than 7 digits when using the 64-bit FPU with an Arduino Due.

      Delete
  3. Hi Brad,

    Thanks for your reply.
    I also thought it is possible.

    But i think its not.
    The difference of the Due is that it has a 32bit chip and 64bit floatingpoint precision i think.
    The Arduino Mega has an 8bit chip with 32bit floating point precision.

    The Arduino Reference for float says "They are stored as 32 bits (4 bytes) of information. Floats have only 6-7 decimal digits of precision."

    So this is actually exactly the same precision that the Arduino Mega (8bit chip) has.

    Thats somehow weird. Why would one buy such an 32bit FPU??? (Exept out of having no clue like me, lol)

    ReplyDelete