## First testrun of the E-Puch

Today I’ve made the first test-run of the E-Puch. As I’ve written about before it is an old ICE moped that I’ve removed the engine and replaced with an electric BLDC outrunner.

Today, me and my brother threw everything together for a quick testrun just to see that everything works, and try out the performance.

I will soon write a post about the motor controller which I ordered from a guy named Lyen on the Endless Sphere forum. It is currently set to limit battery current around 40 A, but I think I could increase the current limit by 50% without any modifications. Which would give 50% more torque.

The motor is mounted on two 5 mm aluminum sheets that are bolted in the original motor holes in the frame.

Except for the motor and motor sprocket the drivetrain is original.

I use 4 bricks of 6S 5 Ah Turnigy 20C batteries mounted in 12S2P configuration. For now these are in a plastic box on the rear end of the moped.

And at last a video of my father trying the moped.

## Plans for my depron plane

In a comment on the post about my first Depron RC-plane I was asked for the plans. I’m afraid I don’t have the nice 1:1 print on multiple A4 plans that most people are used to, but if someone have a good guide on how I create those kinds of prints I’ll be happy to create one. But for now I can provide the drawing with measurements.

And the same drawing as a PDF

I measured up these parts on a piece of cardboard to use as a template. Especially since you need two of all parts except the one in the lower right.

I used the kind of cardboard that you can buy at a painters shop to protect your floor while painting.

## RepRap Prusa Mendel

To mount the sensors on the large outrunner as i wrote about in this post I got a couple of 3D printed plastic parts for holding the hall sensors at exactly 17.14°.

This raised my interest for 3D printing and I started to do some research on which printers that were available. There are several different projects that sell a kit that only needs assembly for example the MakerBot but I decided to go with the RepRap that is a more DIY kind of printer. The main reason of this is that the RepRap seemed to have the highest  buildvolume/price ratio and the community around the RepRap is very large and helpful.

There are several different versions of the RepRap but when I started this build a couple of months ago most people seemed to be building the upgraded Prusa Mendel with LM8UU linear bearings, upgraded z-axis couplings and slight changes in som other plastic parts. The nice thing with a RepRap is that once you’ve built your machine you can print most of the parts needed to build another one. Therefore there are a lot of people around the world selling the plastic parts on for example ebay.

The RepRap can print two different kinds of plastic:

Is made from petroleum and has a quite high melting point. This is the kind of plastic which  LEGO blocks are made of. This plastic is softer than PLA and more flexible.

PLA (PolyLactic Acid)
This plastic is made from corn starch and has a lower melting point than ABS and is a little bit harder but more brittle.

I decided to go with parts in ABS, I’m not sure yet if that was a good choice since I’ve heard that it’s more difficult to produce good quality prints with this plastic. I ordered the plastic parts from a dutch guy on eBay and the first parts I got were pretty bat prints all parts were ugly and the x-axis mounts were so warped the were unusable.

Luckily enough the guy I bought them from were kind enough to send me a new set of parts which were good enough.

Apart from the plastic parts you need what is caled Vitamins, this is all the parts that you cant print on another RepRap. For the Prusa Mendel this is:

• About 3 m 8 mm smooth rod
• A big pile of nuts, screws and washers M3, M4 and M8
• A couple of 608zz ball bearings and LM8UU linear bearings
• Printbed
• 5 Nema 17 stepper motors
• Electronics (for example RAMPS or Sanguinololu)
• ~200-300W 12V power supply

The current status of my build is that I’ve acquired and assembled the first five parts in this list, the rest will be bought when I can spare the money.

The threaded rod, nuts, screws and washers I bought at a local hardware stores (Bauhaus and  Hornbach) and the bearings are from eBay. The smooth rods are from a Swedish webshop called Maskindelen.

To get good quality prints you need a heated printbed and most of the Prusa Mendel DIY kits you can buy includes a heater built on a pcb but since I had a nice sheet of 5 mm aluminum left from the motor mount on the E-Puch, I decided to build my own. The aluminum will be used to spread the heat from three 100 W power resistors mounted underneath the bed. On top of this I will place a 220 x 220 mm piece of glass to print on.

For the rest of the parts I’m pretty sure I’ll buy a Prusa Mendel electronics kit from ReprapWorld togehter with a 12V 348W MeanWell PSU from Sure Electronics on eBay.

## Modifying the Turnigy 80-100 Brushless Outrunner – Part 3

As I’ve written before I had problems getting the Turnigy motor to run in sensored mode using the modified cheap-o eBay controller. Just to se if It’s the controller that is the problem I’ve tried the motor with my e-bike controller.

SUCCESS!

It works perfect! Turns slow and have lots of starting torque. I didn’t try more than 15%-20% throttle and the battery was empty in my current meter so I could’t measure the current. I will try full throttle and measure the current as soon as I’ve got a new battery.

The motor looks much neater with the internal sensors than the external I think I’ll paint it black to match the black moped when I’ve epoxied the stator and not going to take it apart again.

Compared to the externally mounted sensors

## Pitch and roll estimating Kalman filter for stabilizing quadrocopters

A while ago i wrote a document on how you could use a Kalman Filter to merge the sensor readings of a gyro and an accelerometer into pitch and roll for a quadrocopter. This is pretty much a copy/paste of this document with some small adaptions for the blog format. I haven’t got my quadrocopter to fly yet using this filter but I’m pretty sure that it’s possible if I just find the time to trim all paramters of the filter and controller.

The aim of this post is not to present all the equations proving the optimality of a Kalman filter, there is enough papers and books doing that. Instead you should, after reading this, understand my filter implementation enough to be able to tune it for your purposes. Because of this the document may not always be 100% mathematically correct and concepts I do not find important may be left out completely.

To understand this paper you need to know some basic trigonometry and linear algebra. For those of you not comfortable with linear algebra I suggest you to read a little. The Wikipedia articles about matrix multiplication, matrix inversion and matrix transpose could be a good start. I will not go into detail on explaining exactly how the Kalman filter works but I will explain the steps needed to construct such a filter. For a more in-depth view on the Kalman filter I recommend you to read the Wikipedia article or one of the several good books on the subject. This document will however use the same notations as in the Wikipedia article.

The reason I constructed this filter in the first place was to control the pitch and roll of a quadrocopter where neither the accelerometer nor the gyro could be used by itself to get accurate readings. The accelerometer can be used to estimate the direction of the gravity acceleration vector while stationary but this becomes difficult when the quadrocopter is moving since acceleration composants will appear in other directions than downwards. The gyro reading on the other hand can be integrated over time to get the angle relative to starting position but each measurement error will integrate into the angle estimation and the error will build up over time, especially since most gyros have a small bias. One of the solutions of this problem is to fuse the readings from both sensors using a Kalman filter. This filter uses the gyro readings for quick angular changes and the accelerometer to correct the error over longer periods of time. Other solutions like DCM or complementary filters exist but are not explained in this document.

# The filter

A composite Kalman filter for estimating both pitch and roll could be created, taking into account the fact that they are coupled through the accelerometer gravity vector. Such a filter would be very complex and highly nonlinear because of the trigonometry involved forcing us to use an Extended Kalman Filter (EKF). It will probably require a large amount of trigonometry function evaluation and will not, on a microcontroller without hardware floating-point capabilities, yield enough performance to balance a quadrocopter. Instead the filter could be divided into two identical filters one for pitch and one for roll. This not only makes the filter linear but also removes almost all computationally heavy trigonometry functions.

This simplification is based on the fact that the changes in gravity acceleration vector for pitch and roll are more or less independent of each other for small angles when the angle approaches ±90° there will be errors in the output. The filter constructed will work best for small changes of pitch or roll which generally isn’t a problem when stabilizing a quadrocopter. Hence this filter may not be optimal for acrobatic flight performance and maybe more suitable for aerial photography or similar tasks.

# Steps of evaluating the filter

The Kalman filter consists in six steps executed over and over again with a sample time  between the executions. In the notation used in this document a variable is subscripted with  it refers to the value during previous execution and if it is subscripted with  it refers to the value during the current execution. The steps are:

## 1. State prediction based on dynamic model.

One of the most important parts of the Kalman filter is the model of the system. This is the part which keeps the output sane while the sensors are feeding the filter with insane readings. For example reducing the effect of measurement noise or the acceleration vector pointing somewhere else than down due to other acceleration than gravity. The model is used to predict the next state of the model based on the current state and the control signals.

Since we separate the estimation of pitch and roll the quadrocopter state x according to one of the filters can be described by three different variables. Keep in mind that this is for pitch OR roll. Two identical filters are created.

$\boldsymbol{x} = \left[ \begin{array}{c} \theta \\ \dot{\theta} \\ \dot{\theta}_b \end{array} \right]$

The angle  the angular velocity  and the bias in the angular velocity measurements  Using this state representation the equation

$\boldsymbol{x}_k = \boldsymbol{Fx}_{(k-1)} + \boldsymbol{Bu}_k + \boldsymbol{w}_k \: \: (1)$

Can be used to make a good guess of the states in this sample  based on the state in the previous sample  and the current control signal The matrix  represents the dynamics of the system. Multiplied with the old states the result is a guess of the new states. For the quadrocopter the following F matrix is used.

$\boldsymbol{F} = \left[ \begin{array}{ccc} 1 & \Delta t & -\Delta t \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{array} \right]$

If you expand the matrix equation for xk the result will be

$\begin{array}{l} \theta_k = \theta_{(k-1)} + \Delta t(\dot{\theta}_{(k-1)} – \dot{\theta}_{b_{(k-1)}} ) \\ \dot{\theta}_k = \dot{\theta}_{(k-1)} \\ \dot{\theta}_{b_k} = \dot{\theta}_{b_{(k-1)}} \end{array}$

If you think about it, this seems fairly reasonable. The angle in the next sample will be the angle in the sample before plus the unbiased angular velocity multiplied with the sampling time. The model also says that the other two states will remain the same as in the previous sample. This is a simplification saying that the angular velocity and angular velocity measuring bias will change slow enough to be barely noticeable between two sample times.

The next part of equation (1) involves the control signal input to the system. The multiplication with the B matrix can be expanded in exactly the same way as the F matrix but in the case of the quadrocopter inputs are ignored thus

$\boldsymbol{B} = 0$

Inputs could be taken into consideration but this will increase the complexity and computational requirements of the filter and the accuracy gain will probably not be significant.

Just to explain how this works (you can skip this section if you want), let’s say you also feed the filter with the input to the motors affecting the filter angle u1 and u2 and you also know that the force generated by the motor is linearly dependent of the input by the constant k. You also know the inertia Jaround the axis of the angle. You could use

$\boldsymbol{u} = \begin{bmatrix} u_1 \\ u_2 \end{bmatrix}$

$\boldsymbol{B}=\begin{bmatrix} 0 & 0 \\ \frac{k}{J} & \frac{k}{J} \\ 0 & 0 \end{bmatrix}$

resulting in a model for the estimation of the angular velocity looking like this

$\dot{\theta}_k = \dot{\theta}_{k-1} + \frac{k}{J}\left ( u_1 – u_2 \right )$

Since the model is pretty coarse there is a need for something more to take model errors into consideration. It is easy to see that the model for the 2nd and 3rd state will not be 100% accurate all the time. This is where w, which is called model noise, comes in. A zero mean Gaussian noise is added to each state to represent changes that doesn’t agree with the model. In mathematical terms

$\boldsymbol{w} \sim N\left ( 0, \boldsymbol{Q} \right )$

Q is the covariance matrix of the noise in other words how much noise there is and if the noise on one state depends on another state. For the quadrocopter the noise on each state is considered to be independent which makes Q diagonal

$\boldsymbol{Q} = \begin{bmatrix} q_1 & 0 & 0 \\ 0 & q_2 & 0 \\ 0 & 0 & q_3 \end{bmatrix}$

The elements on the diagonal represent how large model errors we expect in the different states and will be an important tuning parameter in the filter. The fact that this matrix is diagonal will allow us to do a lot of optimizations while realizing the filter in C-code later on.

## 2. State covariance matrix update based on model

Another important part of the Kalman filter is the matrix P which represents how much we trust the current values of the state variables. A small P matrix means that the filter has converged close to the real value. When the model predictions in step 1 have been done the P matrix has to be updated according to the uncertainties induced by the model noise w with the covariance Q. This is done with the equation

$\boldsymbol{P}_k = \boldsymbol{FP}_{k-1}\boldsymbol{F}^T + \boldsymbol{Q}$

where the superscript T means that the matrix is transposed. You scale the current value of P with F2 and then add the covariance matrix of the model noise. This hopefully makes sense since you have made a guess on the current states based on a coarse model the uncertainty must increase.

## 3. Model and measurement differences

The next part of the filter is where the new measurements  come in. In this step the difference between the states calculated from the model is compared to what is measured using the equation

$\boldsymbol{y}_k = \boldsymbol{z}_k – \boldsymbol{Hx}_k + \boldsymbol{v}_k$

which introduces the H matrix. This is a matrix which maps the current state on the measurements. In the quadrocopter case we measure the angle based on the gravity vector by using the atan2(b, a) on the acceleration vectors perpendicular to the filters rotational axis and the angular rate measured by the gyro. This results in a measurement vector

$\boldsymbol{z} = \begin{bmatrix} \theta \\ \dot{\theta} \end{bmatrix}$

Since the gyro bias will be a part of the angular rate and cannot be measured we will leave it to the Kalman filter to find out. To map or state vector x onto the measurement vector z we multiply by the matrix

$\boldsymbol{H} = \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \end{bmatrix}$

As with Q the zeros in this matrix reduces the number of multiplications needed when this is realized in C-code allowing further optimizations.

The vector v is similar to w it represents errors in the measurements which are assumed to be zero mean and Gaussian distributed as well

$\boldsymbol{v} \sim N\left ( 0, \boldsymbol{R} \right )$

R is similar to Q the covariance matrix of the measurements. This can be directly related to the sensor quality. As with the Q matrix the sensor errors are assumed to be independent which make the R matrix diagonal as well

$\boldsymbol{R} = \begin{bmatrix} r_1 & 0 \\ 0 & r_2 \end{bmatrix}$

As you may have noticed by now, we like matrices with a lot of zeroes since this allow us to optimize the filter implementation.

## 4. Measurement covariance update

After including new data in form of measurements we need to calculate the covariance matrix of this data which is known as S and is similar in many ways to P. This is calculated with the equation

$\boldsymbol{S}_k = \boldsymbol{HP}_k \boldsymbol{H}^T + \boldsymbol{R}$

You can see that the value of S depends on the covariance of the previous model predictions transformed to the measurement vector through H plus the covariance of the sensor readings. Once again I want to point out that a large covariance matrix means that we have low confidence in the values while a small covariance would mean that the values should be fairly accurate.

## 5. Calculate Kalman gain

Now we are getting close to the part where we merge the knowledge from the model with the measurements. This is done through a matrix called the Kalman gain K This matrix will help us weigh the measurements and the model together. K is calculated by

$\boldsymbol{K}_k = \boldsymbol{P}_k \boldsymbol{H}^T \boldsymbol{S}_k^{-1}$

What is done here may not be obvious at the first glance but makes sense if you think about it. You take the H matrix which maps the states onto the measurements and multiply it with the state covariance and the inverse of the measurement covariance. If we play with the thought that we have large confidence in our model and low confidence in our measurements the resulting K will small. On the other hand if we have low confidence in the model and high confidence in the measurements K will be large.

## 6. Improve model prediction

Now it is time to improve the model prediction by adding the difference between measurements and predictions  to the states predicted in step 1 after scaling it with the gain matrix K

$\boldsymbol{x}_k = \boldsymbol{x}_k + \boldsymbol{K}_k \boldsymbol{y}$

The result  will be the filter output at this sample time. Remember from the previous step that a larger confidence in the model than the measurements will result in a small K decreasing the importance of the measurements  and the opposite if we trust the measurements more than the model.

## 7. Update state covariance with new knowledge

Since we added data in form of measurements to the state vector we need to update the state covariance matrix P which is done by the equation

$\boldsymbol{P}_k = \left ( \boldsymbol{I} – \boldsymbol{K}_k \boldsymbol{H} \right )\boldsymbol{P}_k$

Where I is the identity matrix

$\boldsymbol{I} = \begin{bmatrix} 1 & 0 & 0\\ 0 & 1 & 0\\ 0 & 0 & 1 \end{bmatrix}$

in this case. This can be seen as scaling P down because we are a little bit more certain of the state values after adding measurement knowledge. As you can see P will be growing in step 2 after making predictions based on the model which of course makes us more uncertain of the states and then shrink again in this step after we corrected the predictions with measurements. After this step is done we can wait for the next sample and then start over at step 1.

# Summary

To sum up the filter in the quadrocopter case consists in the following calculations performed at each sample

$\boldsymbol{x}_k = \boldsymbol{Fx}_{(k-1)} + \boldsymbol{Bu}_k + \boldsymbol{w}_k$

$\boldsymbol{P}_k = \boldsymbol{FP}_{k-1}\boldsymbol{F}^T + \boldsymbol{Q}$

$\boldsymbol{y}_k = \boldsymbol{z}_k – \boldsymbol{Hx}_k + \boldsymbol{v}_k$

$\boldsymbol{S}_k = \boldsymbol{HP}_k \boldsymbol{H}^T + \boldsymbol{R}$

$\boldsymbol{K}_k = \boldsymbol{P}_k \boldsymbol{H}^T \boldsymbol{S}_k^{-1}$

$\boldsymbol{x}_k = \boldsymbol{x}_k + \boldsymbol{K}_k \boldsymbol{y}$

$\boldsymbol{P}_k = \left ( \boldsymbol{I} – \boldsymbol{K}_k \boldsymbol{H} \right )\boldsymbol{P}_k$

The filter is tuned by modifying the Q and R matrices

$\boldsymbol{Q} = \begin{bmatrix} q_1 & 0 & 0 \\ 0 & q_2 & 0 \\ 0 & 0 & q_3 \end{bmatrix}$

$\boldsymbol{R} = \begin{bmatrix} r_1 & 0 \\ 0 & r_2 \end{bmatrix}$

 Variable Description q1 How well do the model represent the changes of q2 How well do the model represent the changes of q3 How well do the model represent the changes of r1 How much do we trust the measurement of r2 How much do we trust the measurement of

These variables are relative meaning that increasing one of the variables yields the same result as decreasing all other variables. In the quadrocopter case some pointers could be given about the magnitude of these variables.

• r2 should be larger than r 1 since the gyro readings will not be affected by the quadrocopters acceleration. This will lead to the gyro responding quicker than the accelerometer.
• q3 should be low since the gyro bias change extremely slow.
• r1 should be larger than q1 to prevent acceleration from affecting the angle.
• The relation between q2 and r2 will control how sensitive the angle output is to noise and how quick it will respond to changes.

# Implementation

In some MATLAB inspired pseudocode you could write the filter as:

Since this filter is meant to be run on a microcontroller (a 16-bit Microchip dsPIC in my case), together with some form of control loop for feedback control of the quadrocopter pitch and roll, it is essential to keep execution time down to a minimum. C also lack native support for matrix operations. Because of this I have put both time and effort in expanding and optimizing the equations above.

I also choose to use floating point math instead of fixed point for the c-implementation. There are two reasons for this, I once heard someone say that Kalman filtering needs the dynamic range provided by floating point math. Maybe Q15/Q16 implementation would be enough for this application but the main reason of using floating point match would be me being lazy and the resulting execution time is good enough.

The resulting filter were finally implemented in a dsPIC33 processor running at 40 MIPS allowing for at least 500 Hz sampling still leaving plenty of cycles for executing control algorithms.

## Code example

The filter is divided into two different files. The first is a header file (kalman.h) which contains declarations and definitions. The second is the main file which contains all code (kalman.c).

I will also show an example on how this code can be called on from another file (main.c). Keep in mind that the direction of the axes differs from setup to setup.

## main.c

Thanks Ercan for pointing out my programming error in kalman.c

## Modifying the Turnigy 80-100 Brushless Outrunner – Part 2

This is a picture of the rewound stator. As described un the previous post the stator is now wound for ~90 rpm/V using double 1.5 mm copper wire. To hold the windings in place I use some dabs of low temperature heat glue. This will most certainly melt if I would put 3 kW of power through the motor, but I will replace the heat glue with high-temp epoxy when I know that everything works.

The motor is wound as an Distributed LRK (DLRK) and terminated in Y-mode. Using the notation from the picture below, S1, S2 and S3 are connected to the motor controller and E1, E2 and E3 are soldered together inside the motor.

In the previous post I used ATS177 sensord mounted in a bracket outside the motor. This didn’t work very well with the modified controller. This itme I will try SS441A hall sensors, which are more expensive but thats the sensor that is usually recommended on the Endless Sphere Forum. I will also try to mount the sensors inside the motor which I hope will  be more robust and better looking. The sensors are mounted between slot 1 & 2, 5 & 6 and 9 & 10. Which gives them 120° spacing. To hold them in place before applying epoxy I use the same low-temp heat glue and a little kapton tape.

When I tried this setup with the modified controller it still didn’t run in sensored mode which leads me to suspect that there may be something wrong with this controller. I didn’t have time to do any thorough investigations why but my next step will be to inspect the sensor signals on the oscilloscope and try the motor on my other controller which doesn’t run at all without sensors.

## Replace phase wires on Nine Continent 2809 hub motor

The original phase wires (wires between the motor and controller) on my E-bike are way to thin for the currents they are handling. When I got the motor was equipped with 2 m long 1,5 mm² cables. In low-speed-high-torque situations for example steep hills or starts from a standstill the currents in the phase cable can be several times the battery current. My controller limits the battery current to 27 A but the phase current could sometimes approach 100 A. Doing some calculations with the resistivity ρ=1.68•10-8 Ωm giving the original cables a resistance of

$\frac{1.68\cdot 10^{-8}}{1.5\cdot 10^{-6}} = 0.0112 \: \Omega/m$

Judging by the color I’m not really sure that the original cables are made of copper. They could just as well be made of some other metal which would result in even higher resistance. With the 2 m cables the current path to/from the motor is 4 m and the resistance (excluding the motor resistance) is about

$0.0112 \cdot 4 = 0.0448 \: \Omega$

This may seem pretty low but when constantly running 100 A through this cable the voltage drop on the cables will be ~4,5 V and the losses will be about 450W. This would of course instantly cook the cables and luckily enough the current to the motor is not constant and this current levels will only appear for short periods of time at very low speeds.

Anyways, I decided to replace these cables for the thickest I could fit into the axle where the cables are fed into the motor, as well as shortening these cables as much as possible. What I’ve read is that 12 AWG cables (3.31 mm²) is the thickest you could get through the axle without stripping the insulation and adding something thinner. The original cables have a PTFE insulation which I think is a good idea since PTFE cables generally have thin insulation and is very resistant to heat and mechanical wear. I ordered a couple of meters of 12 AWG PTFE cable from Apex Jr which was tho only place I could find that sold this dimension of wires online in small quantities. This cables are definitely made of tin plated copper which can be seen on the cut surfaces.

Doing the same calculations with the new shorter and thicker cables

$\frac{1.68 \cdot 10^{-8}}{3.31 \cdot 10^{-6}} \cdot 1 = 0.005 \: \Omega$

This will result in a voltage drop of 0.5 V and 50 W losses at 100A which is much more manageable. I guess this will give me some additional efficiency but its probably unnecessary with the current performance of my controller. Later this summer there will probably be a post about re-programming current limits and eventually upgrading the MOSFETs of my controller.

Taking the motor apart was easy, I first removed the side cover on the cable-side by removing the nine hex screws and then used a knife to cut the glue and pry the cover off. Before I did this I made a mark on both the cover and the hub so I can put it back exactly the same way. I’m not sure what tolerances are used when manufacturing these but I don’t want to risk a wobbly wheel.

Getting the wires through the axle was hard work and took me more than an hour, the method that worked for me was to put a thin wire through and the used it to pull through the phase and hall wires all at once. It helped a lot to grease the wires with soap to get them through. I kept the original hall sensor wires.