March 3, 2015, 5:42 am
The Safecast X Kickstarter Geiger counter which I wrote the firmware for contained a MMA7455L 3-axis accelerometer. The MMA7455L is an I2C device and it’s fairly easy to work with.
We didn’t end up doing much with the accelerometer but the readings were stored in the log files. I figured it might be interesting to filter the readings based on device orientation at some point.
Here’s the relevant portion of the code, it was written for the STM32 (and libmaple) but should be easily adaptable for other platforms, accel_read_state wakeups up the accelerometer and grabs a reading, before sending it back to sleep, this fit the use-case in the geiger counter where we were only taking periodic readings.
#include "i2c.h"
#include <stdint.h>
#define ACCEL_I2C I2C1
#define ACCEL_ADDR 0x1D
static struct i2c_dev *i2c = ACCEL_I2C;
static int accel_write(uint8 addr, uint8 value) {
struct i2c_msg msg;
uint8 bytes[2];
int result;
bytes[0] = addr;
bytes[1] = value;
msg.addr = ACCEL_ADDR;
msg.flags = 0;
msg.length = sizeof(bytes);
msg.xferred = 0;
msg.data = bytes;
result = i2c_master_xfer(i2c, &msg, 1, 1);
return result;
}
static uint8 accel_read(uint8 addr) {
struct i2c_msg msgs[2];
uint8 byte;
byte = addr;
msgs[0].addr = msgs[1].addr = ACCEL_ADDR;
msgs[0].length = msgs[1].length = sizeof(byte);
msgs[0].data = msgs[1].data = &byte;
msgs[0].flags = 0;
msgs[1].flags = I2C_MSG_READ;
i2c_master_xfer(i2c, msgs, 2, 1);
return byte;
}
static void accel_wakeup(void) {
/* Set the mode to "measurement", measuring 2g */
accel_write(0x16, 0x04 | 0x01);
}
static int accel_ready(void) {
return (accel_read(0x09) & 1);
}
static int accel_sleep(void) {
return accel_write(0x16, 0);
}
uint8 accel_read_state(int16 *x, int16 *y, int16 *z) {
struct i2c_msg msgs[2];
signed char values[6];
uint8 addr = 0x00; /* 10-bits read value */
int32 result = 0;
accel_wakeup();
for(int n=0;(!accel_ready()) && (n < 10);n++) delay_us(1000);
if(!accel_ready()) return 200;
msgs[0].addr = ACCEL_ADDR;
msgs[0].length = sizeof(uint8_t);
msgs[0].data = &addr;
msgs[0].flags = 0;
msgs[1].addr = ACCEL_ADDR;
msgs[1].length = sizeof(values);
msgs[1].data = (uint8 *)values;
msgs[1].flags = I2C_MSG_READ;
result = i2c_master_xfer(i2c, msgs, 2, 1);
if(result == I2C_STATE_ERROR ) return 100;
if(result == I2C_ERROR_TIMEOUT) return 10;
if (x)
*x = (values[1]<<2) | (values[0]);
if (y)
*y = (values[3]<<2) | (values[2]);
if (z)
*z = (values[5]<<2) | (values[4]);
accel_sleep();
return 0;
}
int accel_init(void) {
return 0;
}
int accel_deinit() {
// suspends accel
accel_write(0x16, 0);
return 0;
}
March 3, 2015, 4:53 am
I’ve previously written about hacking the t5325. But I’ve been interesting in buying one again for another project. In preparation I’ve collected some data on them here.
Manuals
Troubleshooting manual
Getting started (not very useful)
Specs
Feature
|
Description
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Input/output/peripheral Support
|
-
Keyboard: USB keyboard
-
Mouse: USB mouse
-
Printer: Local and/or network printers (RDP, ICA, LPD)
-
Video: DVI-I digital video output (DVI to VGA adapter included)
|
March 3, 2015, 3:26 am
I’ve previously posted about the HY-DIV268N-5A and shown how it can be driven with a function generator and how I used to in my Proxxon CNC Mill conversion.
Using the HY-DIV268N-5A with an Arduino is equally simple. You can use the HY-DIV268N-5A directly, or with the often supplied parallel driver board.
The image below show how the HY-DIV268N-5A should be connected, make sure all the black wires are connected to ground and that the stepper is connected correctly.

Make sure the lights on the HY-DIV268N-5A are correctly illuminated. They wont be if you don’t supply enough voltage/current. Refer to my previous post for specifications.
Once the stepper is correctly connected you should be able to drive the stepper with pulses from the Arduino. Make sure the Enable pin is grounded. And the grounds are common between the driver and the Arduino. All grounds in the system should be connected. Then simply send pulses from the Arduino to the PUL+ pin, pulling DIR+ high/low to change the direction. Use the normal digitalWrite function to do this.
March 3, 2015, 2:36 am
These notes refer to the Linux version of kindlegen.
Using Kindlegen is pretty straight forward, it can process HTML files into mobi format reasonably painlessly, but I did run into a couple of small issues.
I used an HTML file with the following basic format:
<html>
<title>BOOKTITLE</title>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet">
<meta name="cover" content="/home/user/fullpath/to/cover.png">
<body style="margin-top: 100px; margin-bottom: 100px; margin-right: 50px; margin-left: 50px;" >
<h2>Contents</h2>
<a href="#s1">section1</a><br>
<a href="#s2">section2</a><br>
<a href="#s3">section3</a><br>
<a href="#s4">Footnotes</a><br>
<h2 id="s1">section1</h2>
<p>BLAH BLAH BLAH BLAH <sup><a href="#fn1" id="r1">[1]</a></sup>
<h2 id="s4">Footnotes</h2>
<p id="fn1"><a href="#r1">[1]</a>Interesting stuff</p>
Which can then be processed with kindgen simply as:
kindlegen myfile.html
And a mobi file will be generated with the same name as the html file, and in the same directory. Initially I ran into issues processing the cover file and kept getting the error “Cover file not found”. Unlike all the over images in the html file, the meta tag pointing to the cover image has to be the full local path to the file, rather than relative to the html file.
It should also be noted that the CSS linked will be ignored by kindlegen, this makes it easier to process HTML files you’re also using elsewhere.