Tag Archive for 'controller'

Enabling the NRF24L01+ for ACRIS

Okay, it’s finally time for making a wireless version of ACRIS. I’m damn tired of stringing up CAT-5 cable everywhere.

So, I’m exploring possible wireless communications systems. My first choice is those based on the Nordic NRF24L01+ chip, which operates in the 2.4GHz spectrum. You can get a variety of turn-key modules from DealExtreme with PCB antennas or more powerful on-board amplifiers and external antennas for practically nothing.

I started by buying three PCB-antenna modules so that I could characterize them. Three weeks later, they finally showed up.

Designing a Reasonable Firmware Architecture

The next step was to write a library for ACRIS. Ultimately, the goal is to convert the whole system, bootloader and all, to be fully wireless. Of course, instead of just starting by writing some tests, I decided to redo the entire ACRIS firmware architecture. Originally, I was going to work on a separate branch, but then when I saw that Github doesn’t count non-master commits on your dashboard status, I got angry and merged it all into master. I also wrote a shitload of READMEs to describe what everything does (or rather, should do).

I finally learned how to make Makefiles from scratch instead of just going off of random other ones I found on the internet. I swear I’m going to start using make for everything ever now. But anyways, I wrote a framework for building and programming all projects in the [cci]avr/prj[/cci] directory. The new firmware architecture is described in this README.

Writing the NRF24L01+ Driver

After porting all the existing code to the new architecture, it was time to start writing a driver for the NRF24L01+. The NRF communicates with an MCU over SPI. Unfortunately, the ATmega168 only has one SPI module and I wanted to dedicate it only to the TLC5940 LED drivers since they use a non-standard way of latching the data (it’s possible to work around this and support everything on the one SPI bus but this would generate a lot of extra traffic on a bus I’m trying to keep quiet).

So, I decided to use the USART in SPI mode, as Atmel documents in their datasheet. In this mode, a third pin is used for the clock ([cci]XCK[/cci]) and [cci]TXD[/cci] and [cci]RXD[/cci] are used for [cci]MOSI[/cci] and [cci]MISO[/cci]. I was lucky enough to leave the [cci]XCK[/cci] pin unused in the LED controllers, so I can actually rework all of my existing LED controllers really easily.

At the same time, though, I need to make a device that translates commands from UART or USB to packets for the NRF. This means that I must use the USART for regular serial communication and SPI to communicate with the NRF.

So, I wrote a communication layer: a common set of commands for sending and receiving bytes and streams of data. The underlying driver can be selected as either SPI or USART depending on which file is compiled, but the API is the same.

On top of this layer, I wrote the actual driver for the NRF24L01+. Unfortunately, the code so far is pretty rigid. It doesn’t easily handle cases like being able to reconfigure the chip quickly. But it does expose functions for reading and writing registers, flushing buffers, transmitting a packet, set up reception, etc. I still have plenty of work to do on it, such as enabling double-buffering for received payloads, setting up ACK payloads (e.g. for communicating LED controller status information), etc. Maybe I’ll add support for their MultiCeiver architecture (automatic handling of multiple transmitters). Depending on how I intend to use it in the future, I may also modify the SPI architecture to be interrupt/event-based.

After a bunch of debugging, I finally got some test firmware working. Building the project [cci]test-nrf[/cci] with [cci]MODE=tx[/cci] will set the project up to be a transmitter and [cci]MODE=rx[/cci] will set it up as a receiver. When one of each is programmed onto two different boards, they’ll talk to each other and the receiver will spit data out via serial. The result?

The range of the modules is pretty decent. I can reach all the way to the other side of my apartment without any issues. But, the caveat is that the two must be in line-of-sight. Pretty much any wall will completely stop all communication. Now, this is using the 1Mbps data rate with Enhanced ShockBurst enabled. If I disable Enhanced ShockBurst and switch to 250Kbps, I might get better results.

OTOH, I also just bought a few of these modules. They use an external antenna and have onboard amplifiers which boost the gain by a whopping 30dB. So, I’m hoping that I’ll only need one of these and then can use the PCB-antenna modules in all of the lighting controllers for reception. The only possible problem with this is that the receivers may not be able to send back ACKs that the transmitter will hear. In this case, I’ll have to disable Enhanced ShockBurst and come up with some kind of isosynchronous transfer mode where the transmitter won’t care about ACKs. But then I won’t be able to enable auto-retransmission and reprogram the controllers wirelessly, which would really suck.

I’m waiting for some 3.3V LDO regulators to come in from Digikey so that I can rework the LED controllers. Right now, I’m using LM317s with a bunch of trimming resistors to make the supply voltage around 3V3.

ACRIS LED Bootloader Ready!

The last major hurdle for the LED controller is finally done. I’ve finished designing a bootloader that allows you to program the device over the RS-485 network, thereby eliminating the difficulties I had originally experienced with in-circuit JTAG programming. I’ve also finished a Python library and application that makes working with the bootloader quite easy.

I just need to do one final verification of the LED controller boards and then I’ll order some. After that, it’s just a matter of assembly and writing some programs to control the colors of the system.

Controlling a Mouse with a MIDI Controller

I’ve been doing a lot of editing of large documents recently and some of them require lots of scrolling in either horizontal or vertical directions. Scrolling vertically is pretty easy thanks to my Logitech MX Revolution, which has an inertial scroll wheel — quite possibly the best invention ever. But quickly scrolling horizontally is basically impossible because it just has a rocker.

I glanced over at my MIDI controller and thought that it would be pretty great if I could use it to emulate scrolling. The Numark TotalControl has two jog wheels that can spin freely in an inertial manner.

I then discovered PyMouse and PyGame’s MIDI module. Using these two libraries, I cooked up this example, which uses the left wheel to scroll vertically and the right wheel to scroll horizontally.

The script simply initializes and finds a suitable MIDI controller. Then, it connects to that controller and periodically polls to see if there have been any events. If so, it processes the event to see if it’s something to scroll with. I implemented an overly-simple “low pass filter” which doesn’t even take advantage of the fact that the TotalControl outputs a number that increases as you scroll faster on the jog wheels, but it works well enough. Future iterations will have more complicated algorithms. Theoretically, this script is cross-platform since the libraries it uses are.

At any rate when you run this script, you can use the jog wheels to scroll. You need to patch PyMouse though. The developer forgot to include support for horizontal scrolling, but this patch changes a whopping two lines to add it (in reality, all of that code needs to be redone because it isn’t very well designed, but I’m lazy).

I’m sure MIDI mappers have been made before, but I’d like to make one where you can just script the controller in Python. You would just register a bunch of hooks (functions based on controller and control number) with calls to whatever functions you want to design. A project for when I’m bored and without internet access, I guess.

Numark Total Control and M-Audio X-Session Pro Mappings for Mixxx

Mixxx’s MIDI scripting engine is amazing. It lets you customize your MIDI controller to a level lower than almost every other DJ software.

A while ago, I made a pretty complex mapping for my M-Audio X-Session Pro. Buttons can perform different actions based on context. For example, holding the headphone button and then pressing another button will perform a different function than just pressing that button in the first place. If you press the headphone button without pressing another button, it will act as a normal PFL toggle button.

I then bought a refurbished Numark Total Control. It has lots of controls and status lights. The existing mapping that was in Mixxx was a bit old, so I decided to write a completely custom mapping. This mapping has a variety of interesting features. Buttons generally have two functions (press the “Key” button to activate the other function). There’s some good looping and hotcue support in there too. Furthermore, depending on whether you have vinyl control enabled or not, some of the controls will behave slightly differently to maximize functionality.

There’s a full table of the features on my Mixxx project page.

Lastly, I started designing a mapping for the X-Session Pro that would allow it to act as an auxiliary controller. This mapping primarily uses all of the buttons as hotcues, again with left and right shift buttons. It also has hotcues for the sampler. There’s a table describing all the features on the page.

Seven Segment LED Control FPGA Module

I was bored last night, so I decided to write up a small module for my Nexys2 that would allow me to easily control the 4-digit 7-segment LED display on the board. Quite simply, this module allows you to enter a single 16-bit number and the corresponding hex value will be written out on the display. You can also set any number of the four decimal points. There is another input mode as well: if you want to update just a single digit of of the array, you can give that a new value without disturbing the others. Here’s the obligatory photo:

You can download the VHDL module here. I’ve also written a small testing environment that takes the output of some UART like Digilent’s RS232 module and uses two bytes of data to set the corresponding numbers on the display.

The module is really simple to use. First, you may need to set the CLKDIVAMT value inside the module depending on your oscillator (I used a 50MHz oscillator); the internal clock divider simply just sets the refresh rate of the display (since we update one digit at a time, we must update them fast enough so that the user doesn’t see any flickering).

Next, when you instantiate the component, you’ll need to feed in your clock, a reset signal (I haven’t tested this, but it should set the numbers all to 0), and specify the output anodes and cathodes of the LEDs on your board (for a seven segment LED, I wired ctout(7) to the decimal point value). Next, you need to take care of inputting the data.

The easiest way to input data is to set useseg to ‘0’ and then feed in a 16-bit number into val and set wen (write enable) to ‘1’. This will push in new data for the display to show.

To enter decimal points, set or clear the corresponding values in dp and then use the wendp enable mask to perform an action. For example if you set dp <= "1101" and wendp <= "1110", the module will turn the decimal points on for the two most significant digits and turn the decimal point off for the third most significant digit, but it won't change the least significant because wendp(0) is 0. Finally, there is one other way to control the digits, using the seg{3,2,1,0} signals. With this mode, you can update a single segment without affecting the others. To do this, set useseg <= '1', seg{3,2,1,0} to whatever 4 bit values you'd like (again, you don't have to set all of them), and set wenseg to the mask of values that you want to change (it works like wendp -- if you set wenseg <= "1001", the most significant digit and least significant digit will be updated).