PLUME – Mastering the codec


It’s been a long time since I posted for the last time.

Since last time, I have continued the calculation on the Kalman filter to see if using one with only a position measure would be useful (it is called alpha-beta-gamma filtering). It brings almost nothing to the system as we have it today (200 mesures per seconds – 1 centimeter standard deviation on measure – 10 m/s^2 input acceleration noise). It improves the precision by less than one percent. So we won’t use it.

Then I worked with the codec evaluation we received. ( In our system the codec will be commanded in SPI and the data will be retrieved using I2S. I had to write a program on an stm32f4 discovery to configure the codec and retrieve the data using I2S,  DMA and ChibiOS.
I had some troubles setting up the SPI, I2S and DMA. I solved the ones with SPI and I2S using the logic analyzer.
One of the most annoying problem was that I was not using the right DMA channel for I2S. I was using a channel called something like DMA_I2S2_ext, which is useful only when the full duplex mode of I2S is set up. The right one is called something like DMA_SPI2_RX (I2S uses SPI pins on STM32F4). Once the right channel was set up, the DMA run  nicely, with double buffering.

Once the the communication with the codec was set, I needed to configure it. The software given by TI to make tests with the the codec evaluation board uses a script language which looks like this to configure the codec : # Select Page 1
w 30 00 01
# Powerup MIC BIAS
w 30 33 40
# Route IN3L to LEFT_P with 10K input impedance
w 30 34 04
# Route IN3R to LEFT_M with 10K input impedance
w 30 36 04
# Unmute Left MICPGA
w 30 3b 00
In the first line, 0x30 is the I2C address of the codec (because we use SPI, we don’t need this value), 0x00 is the register in which the value is written and 0x01 is the value. I wrote I small program to convert a script in a binary file (removing the 0x30’s) to be able to use objcopy and make to link the configuration with the discovery program. I used the default script which records from the inboard microphone and it didn’t work. So I launched the TI software and used the logic analizer to see what was sent by the TI program given the script (I set up the program to use SPI).  I didn’t send what was in the script. In the register address byte, the address is only 7-bit and there is bit used to tell if the value will be read or written. I thought this bit was the MSB because the register addresses go from 0 to 127, but in fact the bit used is the LSB. So for example the line “w 30 34 04” sends “0x68 0x04” on the SPI (the register address is shifted one bit left). So i corected my program. But now it still does not work and i don’t know why so I will continue to search to get it working. My next test is to send the configuration using the TI software and the to give the I2S clocks using the discovey to see what happens.

PLUME – These last few days: Curve Fitting and Kalman Filter

I have done quite a lot of things since the last time i posted something here. I did mainly programming.

I implemented C++ classes for the computational part of the emitter and the receiver. It was a bit straight-forward. The receiver has a method to be set the voltages and a method to get the degrees of freedom. The emitter has a method to retrieve its calibration matrix.

Then we talked among us  and discovered that the symmetry problem would be hard to tackle: Because we have the absolute value of the voltages in the receiver coils, the receiver can be in each one of the each space octants (we only know the absolute values of the coordinates x,y,z).

So I tried to solve it by knowing the initial position and estimating the position in the future. When it is estimated that the receiver will change of octant, the 3-bit sign mask that will be used to compute the next signed position is changed accordingly to estimation. To estimate the position, I fit each of the coordinates with a parabola. the parabola is fitted using the 128 last-known position. Sadly it didn’t work well, there was to much noise in the position and it failed sometimes but enough often to be bad.

Then the group decided to add an IMU to the system to be used to solve the symmetry problem. And around the same time, we discovered that the phase of the measured voltages could be used to solve a part of the symmetry problem. It reduces the problem to a central symmetry. We can get the phases because to measure the voltages we already do a fft on the receiver.

Then I decided to read about kalman filters to see if we could use one to combine the data from the coils and the IMU to get a better precision. I did experiments on an axis combing position data (given by the coils) and accelerometer data assuming that we don’t have the voltage phase. Because the measured position is the absolute value of the real position, I had to use the non linear form of the Kalman filter (the discrete-time extended Kalman filter). Luckily the abs function is a simple non-linear function, so the jacobian matrix was simple (just a sign(x) instead of a 1 ). It works way better than the position estimation method with a parabola. The filter manages to estimate the position given the absolute value of the position and the acceleration, which solves the symmetry problem.

An hour ago, we found out that waiting for the IMU chip will add us a week delay. So we won’t have one.

I hope the phase method will work fine.



These last days I have worked with my team to choose the component and do the PCB. We need to finish the PCBs by friday, so we are in a hurry to finish them.

When I was looking at the audio codecs to see if we could use one to get a neat sinusoidal signal in the emitter coils, I found a codec with a big entry amplification which could be used to sample the signal in the receiver coils. My teammates found this codec nice too, so for the project we will use three of them (one per receiver coil) instead of making an home solution with PGAs and ADCs.

I have also spent time:

  • choosing a led driver : we will have a lot of RGB leds on the emitter.
  • choosing some of the pins on the STM32 to link to the codecs.
  • reading datasheets to see how we can adapt the receiver coils signal to the codec inputs (We need it to be centered around 0.9v instead of 0v)

Communication Challenge


Friday it was the communication challenge. It was tough: it began at 8:30 and ended at 23:30. There were several steps to complete. In the first step we had to retrieve the instructions on a server using the STM32 board. The next steps were about listening to sound downloaded from the server through headphones using the board.

In order to get the headphones working, I had to set up the audio codec, which uses I2S. Once it was done, I was able to listen to the first audio instruction by downloading it entirely to the board RAM. It contained the path to the next audio instruction. The next audio instruction was too big for the board RAM so I had to implement a “streaming” system to hear it. Each time a packet containing audio was downloaded, it was put in a queue. I set up an interrupt to fire up when the codec was ready to get a sample (64k times per second) to feed the codec a 16-bit sample from the queue. It worked fine.

By luck, I had not major problems or mysterious bug during  the communication challenge so I managed to finish it the first. Now I can get back to the PLUME project. I hope there will be enough free time during the Athens week (which I will spend in Télécom) to make progress on it.

PLUME – Calibration


These last few days I have worked on the calibration of the magnetic system. We want the calibration to be as easy as possible. By easy, I mean we will not have to measure precisely the position of the receiver to calibrate. The solution we have come up with is to fix the receiver on an optical table.We don’t know the position of the table nor its orientation.

Once the receiver is on the table ,we slide it several times by a known amount. s. At each position the measure the voltages in the receiver coilThese voltages are used  to compute : the position of the optical table, its orientation, and the two calibration matrix.

These values are found using a gradient descent in Octave,but the result are not satisfactory yet. Octave stops the algorithm when the gradient is too low and I have not found yet how to prevent it. I get a ~5-10cm precision using the artificially noised measures (the measures are simulated) after calibration. I hope there won’t be too much noise on the real system.

PLUME – Getting the location


These last few days I worked on the software prototype. I did many calculations and spent a lot of time using Octave. It paid out and now the software prototype on Octave to get the location and the rotation of the receiver is done. It works without using a converging method, which is good because it is fast.

It works this way:

  • The 9 (3 emitters vand 3 receivers) voltages are put in a matrix
  • Using this matrix, the normalized-field matrix is computed. It is the matrix with the values we get when we get rid of the emmiter and receiver gains and the physic constants. This matrix depends only on the position and orientation of the receiver, not on the emitter nor the receiver characteristics.
  • Then this matrix is symetrized because theoritically it is symetric.
  • With the symetric matrix we compute the position of the receiver.
  • To get the orientation we compare the symetric matrix we measured, which in the base of the receiver, with the theoritical field matrix,which is in the base of the emmiter at the position we just computed, which is in the base of the emmiter. We get the rotation matrix of the receiver.

With this method, I think we get as much precision as we can.

Now, I am working on the calibration. The values obtained from it will be used to get the normalized-field matrix with the voltages. We could compute the calibration values using the characteristics of the coils but we are almost sure it won’t work as expected.


PLUME – Software Prototype


Today I wrote Octave functions to compute the magnetic field using the magnetic dipole model. Then I wrote a solving function which computes the position with the values of the three magnetic fields. I did some computer tests (choose a position, compute the fields, get the position with the fields) and it seems to work.
Now we have to test it with values measured on the test bench.

I also made calculations with Marc-O on the circular spire model (we will need it if the dipole model is not precise enough). We computed the taylor series of the inexpressible functions (see my previous log entry) and computed a majoration of their respective errors. We also made research on a method to find the change of basis matrix of the receptor. The calculation is trivial if we want to get only a change of basis matrix, but if we want an orthogonal matrix it is more complicated. We found an article about it ( and we need to study it.



PLUME – The magnetic field model


Today I continued the calculation the for the magnetic field generated by a circular coil in any position. I can express the field using f1(x)=integral(1/(1-x*cos(t)),t,0,2*pi) and f2(x)=integral(cos(t)/(1-x*cos(t)),t,0,2*pi).

These functions are not expressible using commons functions but they can be expressed using first-kind and second-kind elliptic integral functions for which a C implementation could be found (not in math.h). The implementation seems slow so if we use these magnetic field model, it might be better to approximate f1 and f2 by polynoms. We always have 0<=x<1.

I also discussed with Marc-O about the model. He made the calculations using the magnetic dipole model for the coil, which is an approximation for a small circular coil. He already has results about the calculation of the position so we decided that we will keep his model. We will eventually switch to my model later if we find that the dipole model approximation is not precise enough.

PLUME – Difficult Physics

Today I tried to solve the value the magnetic field vector at an arbitrary position for a field generated with simple coils such as a circle or a square. For the circle coil, the analytical expression of the field can not be expressed using common functions (exp, log, tan…). I still hope to express the “unexpressible” primitive functions with easy-to-compute series. For the square, the field can be calculated quite easily but the answer is long and ugly. Moreover, if we buy coils for the project, they will probably be circular.

I also searched for documents the matricial Newton-Raphson method. We will probably use to solve for the position of the of the receiver using the formula of the magnetic field vector.

Next, I need to continue the calculation of the magnetic field for a circular coil.