Saturday, November 21, 2015

Raspberry I2C bus scanner

The most important thing I need to solve while migrating from BeagleBone to Raspberry Pi is how would I control my PWM modulator via I2C bus.
My Raspbian didn't have a /dev/i2c* devices out of the box so I can't just copy my python scripts to Pi. That is not actually a problem and can be fixed easily.
But what about a new challenge?
So I decided to go a level lower and control my amplifier via BCM 2835 library by Mike McCauley from a C++ program. Never wrote a C++ Linux program before so why not?

I must say there is no fun to use something like nano or vim and plain gcc. I personally not a masochist so I would stay with python if I had to do that 'traditional' way. But luckily for us, Oracle has NetBeans IDE that makes it possible to program and debug any Linux device remotely. 
That's a different story how to make it work and how to elevate permissions to debug a program that interacts with hardware, but it is easy to google out.

Since I didn't want to take apart my only working amplifier I started with a random I2C device I had on hands - a little board that has DS1307 RTC clock and 24C32 EEPROM,

Also as I mentioned before, my Linux didn't have I2C bus enabled so I couldn't use i2cdetect tool. As a result now I have my own I2C bus tester.
So here it is on GitHub.

And for the setup I have
the output is
        +0      +1      +2      +3      +4      +5      +6      +7      +8      +9      +a      +b      +c      +d      +e      +f
0       .       .       .       .       .       .       .       .       .       .       .       .       .       .       .       .
10      .       .       .       .       .       .       .       .       .       .       .       .       .       .       .       .
20      .       .       .       .       .       .       .       .       .       .       .       .       .       .       .       .
30      .       .       .       .       .       .       .       .       .       .       .       .       .       .       .       .
40      .       .       .       .       .       .       .       .       .       .       .       .       .       .       .       .
50      O       .       .       .       .       .       .       .       .       .       .       .       .       .       .       .
60      .       .       .       .       .       .       .       .       O       .       .       .       .       .       .       .
so I clearly see two devices on addresses 0x50 and 0x68.

Next step is to rewrite and simplify my python scripts in C++. And use them from a NodeJS app.
But stop! Here a legitimate question pops up: why bother with C++ when I could use existing Node I2C libraries? 
The answer is simple: I already fried my tweeters other day and I wish my speakers to live longer. So I can't trust an asynchronous Node process that calls python scripts whenever I want to access the I2C bus. It is not about the speed, the speed might be good enough to control the volume or mute/unmute the PWM. I just don't want Node event loop to be in control of timings. Probably it sounds old-stylish but I believe the lower you go controlling hardware the better.
I dream about a character device driver but it seems too complex for me at the moment because I'm a total newbie in Linux programming. So let's see what I can come up with later.