Build a Quadcopter

How To Build A Quadcopter – Choosing Hardware

In this article I will be talking about quadcopter components and how to choose them. This is part of the tutorial series on how to build a quadcopter. In the next post I will be talking about software, how to go about the algorithm and programming.

If you are planning on building a quadcopter but not sure how, this is the right place for you. Doing research is pretty boring, so I am trying to put together a comprehensive tutorial about quadcopter, hope it helps you as much as it helped me.

Building a quadcopter from scratch takes a lot of time and effort. If you are inpatient, afraid of programming/maths and has a good budget, you can just buy a pre-built kit. You could get it assembled within minutes before it’s flying (For example, like this one). But I have to say, you are missing the fun part of building a quadcopter. From choosing the parts, designing the circuits, to programming, you will be involved in every aspect of building a quadcopter, and it’s FUN!

If you have any questions, feel free to ask on this quadcopter message board.

This blog post is divided into a three parts

  • What is a Quadcopter and How It Work
  • Quadcopter Components Introduction
  • Conclusion

What Is A QuadCopter and How It Works

QuadCopter is a helicopter with four rotors, so it’s also known as quadrotor. Because of its unique design comparing to traditional helicopters, it allows a more stable platform, making quadcopters ideal for tasks such as surveillance and aerial photography. And it is also getting very popular in UAV research in recent years.

The Quadcopters exist in many different sizes. From as small as a CD up to something as big as one meter in width.

tiny-quadcopter   large_Quad_Copter_01

On a regular helicopter has one big rotor to provide all the lifting power and a little tail rotor to offset the aerodynamic torque generated by the big rotor (without it, the helicopter would spin almost as fast as the propeller)

Unlike a helicopter, a quadrotor has four rotors all work together to produce upward thrust and each rotor lifts only 1/4 of the weight, so we can use less powerful and therefore cheaper motors. The quadcopter’s movement is controlled by varying the relative thrusts of each rotor.

These rotors are aligned in a square, two on opposite sides of the square rotate in clockwise direction and the other two rotate in the opposite direction. If all rotors turn in the same direction, the craft would spin would spin just like the regular helicopter without tail rotor. (if you are not sure what I mean, check out this video) Yaw is induced by unbalanced aerodynamic torques. The aerodynamic torque of the first rotors pair cancelled out with the torque created by the second pair which rotates in the opposite direction, so if all four rotors apply equal thrust the quadcopter will stay in the same direction.

quadcopter-station

To maintain balance the quadcopter must be continuously taking measurements from the sensors, and making adjustments to the speed of each rotor to keep the body level. Usually these adjustments are done autonomously by a sophisticated control system on the quadcopter in order to stay perfectly balanced. A quadcopter has four controllable degrees of freedom:Yaw, Roll, Pitch, and Altitude. Each degree of freedom can be controlled by adjusting the thrusts of each rotor.

  • Yaw (turning left and right) is controlled by turning up the speed of the regular rotating motors and taking away power from the counter rotating; by taking away the same amount that you put in on the regular rotors produces no extra lift (it won’t go higher) but since the counter torque is now less, the quadrotor rotates as explained earlier.3.- control becomes a matter of which motor gets more power and which one gets less.
  • Roll (tilting left and right) is controlled by increasing speed on one motor and lowering on the opposite one.
  • Pitch (moving up and down, similar to nodding) is controlled the same way as roll, but using the second set of motors. This may be kinda confusing, but roll and pitch are determined from where the “front” of the thing is, and in a quadrotor they are basically interchangeable; but do take note that you have to decide which way is front and be consistent or your control may go out of control.

quadcopter-rotating

quadcopter-foward

For example, to roll or pitch, one rotor’s thrust is decreased and the opposite rotor’s thrust is increased by the same amount. This causes the quadcopter to tilt. When the quadcopter tilts, the force vector is split into a horizontal component and a vertical component. This causes two things to happen: First, the quadcopter will begin to travel opposite the direction of the newly created horizontal component. Second, because the force vector has been split, the vertical component will be smaller, causing the quadcopter to begin to fall. In order to keep the quadcopter from falling, the thrust of each rotor must then be increased to compensate.

This illustrates how the adjustments made for each degree of freedom must work together to achieve a desired motion. Now, building and flying a quadrotor from a remote control is simple and fun and stuff, but people noting the inherently stable flight (in theory with equal speed of the motors the thing keeps itself level) and ease of control (only three functions and they are all basically take speed from one and put in the other), people love to make them autonomous (flies itself) and semi-autonomous (at least keeps itself level by responding to disturbances and error).

Quadcopter Components Introduction

There are sensors connected to a microcontroller to make the decision as to how to control the motors. Depending on how autonomous you want it to be, one or more of these sensors are used in combination.

In this section, I will talk about these essential quadcopter components:

  • Frame – The structure that holds all the components together. They need to be designed to be strong but also lightweight.
  • Rotors – Brushless DC motors that can provide the necessary thrust to propel the craft. Each rotor needs to be controlled separately by a speed controller.
  • Propeller
  • Battery – Power Source
  • IMU – Sensors
  • Microcontroller – The Brain
  • RC Transmitter
  • Optional

Before we go into explaining how to choose each components, we can take a look some quadcopters that people have built, and the parts they used to get a rough idea. I didn’t build these planes, so I can’t guarantee their performance.

Multicopter Examples Page

Frame

Frame is the structure that holds all the components together. The Frame should be rigid, and be able to minimize the vibrations coming from the motors.

Aluminium-Frame

A QuadCopter frame consists of two to three parts which don’t necessarily have to be of the same material:

  • The center plate where the electronics are mounted
  • Four arms mounted to the center plate
  • Four motor brackets connecting the motors to the end of the arms

Most available materials for the frame are:

  • Carbon Fiber
  • Aluminium
  • Wood, such as Plywood or MDF (Medium-density fibreboard)

Carbon fiber is most rigid and vibration absorbent out of the three materials but also the most expensive.

Hollow aluminium square rails is the most popular for the QuadCopters’ arms due to its relatively light weight, rigidness and affordability. However aluminium could suffer from motor vibrations, as the damping effect is not as good as carbon fiber. In cases of severe vibration problem, it could mess up sensor readings.

Wood board such as MDF plates could be cut out for the arms as they are better at absorbing the vibrations than aluminium. Unfortunately the wood is not a very rigid material and can break easily in quadcopter crashes.

Although it is not as important as for the arms which of the three material to use for the center plate, plywood is most commonly seen because of its the light weight, easy to work with and good vibration absorbing features.

As for arm length, the term “motor-to-motor distance” is sometimes used, meaning the distance between the center of one motor to that of another motor of the same arm in the QuadCopter terminology.

QuadCopter-M2M-Distance

The motor to motor distance usually depends on the diameter of the propellers. To make you have enough space between the propellers and they don’t get caught by each other.

[Give example]

Brushless Motors

A little background of Brushless motor. They are a bit similar to normal DC motors in the way that coils and magnets are used to drive the shaft. Though the brushless motors do not have a brush on the shaft which takes care of switching the power direction in the coils, and this is why they are called brushless. Instead the brushless motors have three coils on the inner (center) of the motor, which is fixed to the mounting.

brushless_motor_1

On the outer side it contains a number of magnets mounted to a cylinder that is attached to the rotating shaft. So the coils are fixed which means wires can go directly to them and therefor there is no need for a brush.

brushless_motorBrushlessMotor

Generally brushless motors spin in much higher speed and use less power at the same speed than DC motors. Also brushless motors don’t lose power in the brush-transition like the DC motors do, so it’s more energy efficient.

Brushless motors come in many different varieties, where the size and the current consumption differ. When selecting your brushless motor you should take care of the weight, the size, which kind of propeller you are going to use, so everything matches up with the current consumption. When looking for the brushless motors you should notice the specifications, especially the “Kv-rating“.

The Kv-rating indicates how many RPMs (Revolutions per minute) the motor will do if provided with x-number of volts. The RPMs can be calculated in this way: RPM=Kv*U An easy way to calculate rating of motor you need, check out the online calculator eCalc. It’s an amazing tool that helps you decide what components to purchase depending on the payload that you want to carry.

Make sure you buy the counter-rotating to counteract the torque effect of the props.

I have written a more complete guide on how to choose Motor and propeller.

Propellers

On each of the brushless motors there are mounted a propeller.

You might not have noticed this on the pictures, but the 4 propellers are actually not identical. You will see that the front and the back propellers are tilted to the right, while the left and right propellers are tilted to the left.

Like I mentioned before, 2 rotors rotates in the opposite directions to the other two to avoid body spinning. By making the propeller pairs spin in each direction, but also having opposite tilting, all of them will provide lifting thrust without spinning in the same direction. This makes it possible for the QuadCopter to stabilize the yaw rotation, which is the rotation around itself.

images

The propellers come in different diameters and pitches (tilting). You would have to decide which one to use according to your frame size, and when that decision is made you should chose your motors according to that. Some of the standard propeller sizes used for QuadCopters are:

  • EPP1045 10 diameter and 4.5 pitch  this is the most popular one, good for mid-sized quads
  • APC 1047 10 diameter and 4.7 pitch  much similar to the one above
  • EPP0845  8 diameter and 4.5 pitch  regularly used in smaller quads
  • EPP1245  12 diameter and 4.5 pitch  used for larger quads which requires lot of thrust
  • EPP0938  9 diameter and 3.8 pitch  used in smaller quads

Aerodynamics is just way too complex for non-academic hobbyists. It’s even unlikely we can explain all that theory stuff in a few words. But in general when selecting propellers you can always follow these rules:

  1. The larger diameter and pitch the more thrust the propeller can generate. It also requires more power to drive it, but it will be able to lift more weight.
  2. When using high RPM (Revolutions per minute) motors you should go for the smaller or mid-sized propellers. When using low RPM motors you should go for the larger propellers as you can run into troubles with the small ones not being able to lift the quad at low speed.

Analysis of Propeller Pitch, Diameter, and RPM

Pitch VS Diameter: the diameter basically means area while pitch means effective area. So with the same diameter, larger pitch propeller would generate more thrust and lift more weight but also use more power.

A higher RPM of the propeller will give you more speed and maneuverability, but it is limited in the amount of weight it will be able to lift for any given power. Also, the power drawn (and rotating power required) by the motor increases as the effective area of the propeller increases, so a bigger diameter or higher pitch one will draw more power at the same RPM, but will also produce much more thrust, and it will be able to lift more weight.

In choosing a balanced motor and propeller combination, you have to figure out what you want your quadcopter to do. If you want to fly around stably with heavy subject like a camera, you would probably use a motor that manages less revolutions but can provide more torque and a longer or higher pitched propeller (which uses more torque to move more air in order to create lift).

ESC – Electronic Speed Controller

The brushless motors are multi-phased, normally 3 phases, so direct supply of DC power will not turn the motors on. Thats where the Electronic Speed Controllers (ESC) comes into play. The ESC generating three high frequency signals with different but controllable phases continually to keep the motor turning. The ESC is also able to source a lot of current as the motors can draw a lot of power.

ESC-Turnigy-Plush

The ESC is an inexpensive motor controller board that has a battery input and a three phase output for the motor. Each ESC is controlled independently by a PPM signal (similar to PWM). The frequency of the signals also vary a lot, but for a Quadcopter it is recommended the controller should support high enough frequency signal, so the motor speeds can be adjusted quick enough for optimal stability (i.e. at least 200 Hz or even better 300 Hz PPM signal). ESC can also be controlled through I2C but these controllers are much more expensive.

When selecting a suitable ESC, the most important factor is the source current. You should always choose an ESC with at least 10 A or more in sourcing current as what your motor will require. Second most important factor is the programming facilities, which means in some ESC you are allowed to use different signals frequency range other than only between 1 ms to 2 ms range, but you could change it to whatever you need. This is especially useful for custom controller board.

Battery

As for the power source of the quadcopter, I would recommend LiPo Battery because firstly it is light, and secondly its current ratings meet our requirement. NiMH is also possible. They are cheaper, but it’s also a lot heavier than LiPo Battery.

Battery-Zippy-4000

Battery Voltage

LiPo battery can be found in a single cell (3.7V) to in a pack of over 10 cells connected in series (37V). A popular choice of battery for a QuadCopter is the 3SP1 batteries which means three cells connected in series as one parallel, which should give us 11.1V.

Battery Capacity

As for the battery capacity, you need to do some calculations on:

  • How much power your motors will draw?
  • Decide how long flight time you want?
  • How much influence the battery weight should have on the total weight?

A good rule of thumb is that you with four EPP1045 propellers and four Kv=1000 rated motor will get the number of minutes of full throttle flight time as the same number of amp-hours in your battery capacity. This means that if you have a 4000mAh battery, you will get around 4 minutes of full throttle flight time though with a 1KG total weight you will get around 16 minutes of hover.

Battery Discharge Rate

Another important factor is the discharge rate which is specified by the C-value. The C-value together with the battery capacity indicates how much current can be drawn from the battery.

Maximum current that can be sourced can be calculated as:

MaxCurrent = DischargeRate x Capacity

For example if there is a battery that has a discharge rate of 30C and a capacity of 2000 mAh. With this battery you will be able to source a maximum of 30Cx2000mAh = 60A. So in this case you should make sure that the total amount of current drawn by your motors won’t exceed 60A.

This tutorial about battery I found very informative.

IMU – Inertial Measurement Unit

The Inertial Measurement Unit (IMU) is an electronic sensor device that measures the velocity, orientation and gravitational forces of the quadcopter. These measurements allow the controlling electronics to calculate the changes in the motor speeds.

The IMU is a combination of the 3-axis accelerometer and 3-axis gyroscope, together they represent a 6DOF IMU. Sometimes there is also an additional 3-axis magnetometer for better Yaw stability (in total 9DOF).

How does IMU work

The accelerometer measures acceleration and also force, so the downwards gravity will also be sensed. As the accelerometer has three axis sensors, we can work out the orientation of the device.

Accelerometer-3-axis

A gyroscope measure angular velocity, in other words the rotational speed around the three axis.

Gyroscope-3-axis

Using Only Accelerometer?

With the accelerometer alone, we should be able to measure the orientation with reference to the surface of earth. But the accelerometer tends to be very sensitive and unstable sometimes, when motor vibration is bad, it could mess up the orientation. Therefore we use a gyroscope to address this problem. With both the accelerometer and gyroscope readings we are now able to distinguish between movement and vibration.

Using Only Gyroscope?

Since the gyroscope can tell us the rotational movement, why can’t we just use the gyroscope alone?

The gyroscope tends to drift a lot, which means that if you start rotating the sensor, the gyroscope will output the angular velocity, but when you stop it doesn’t necessarily go back to 0 deg/s. If you then just used the gyroscope readings you will get an orientation that continues to move slowly (drifts) even when you stopped rotating the sensor. This is why both sensors has to be used together to calculate a good and useful orientation.

Magnetometer

The accelerometer cannot sense yaw rotation like it can with roll and pitch, and therefore a magnetometer is sometimes used.

A magnetometer measures the directions and strength of the magnetic field. This magnetic sensor can be used to determine which way is south and north. The pole locations are then used as a reference together with the Yaw angular velocity around from the gyroscope, to calculate a stable Yaw angle.

I am trying to keep the theory and maths minimal here, and I will go into more detail in the next couple of tutorials.

Buying an IMU

These three sensors are available individually on the market. But it is easier for development to get an IMU sensor board with the first two sensors (6DOF) or all three sensors (9DOF).

9DOF-Stick-Front

The raw sensor boards can communicate with the microcontroller via I2C or analogue. Digital boards that support I2C is easier and faster for development, but Analogue ones are cheaper.

There are even complete IMU units with processor available. Usually the processor is a small 8-bit microprocessor which runs computations some kind of algorithms to work out the Pitch, Roll and Yaw. The calculated data will then be put out on a serial bus or sometimes also available by I2C or SPI.

The choice of IMU is going to narrow down what type of controller board you can use. So before purchasing an IMU boards you should find out information about the controller boards. Some controller boards even comes with built-in sensors.

Some commercially available IMU sensors boards:

IMU with processor:

Flight Controller – Controlling electronics

You can either buy a controller board that is specially designed for quadcopter or buy all the parts and assemble one yourself. Some of the controller boards already contain the required sensors while other requires you to buy these on a separate board.

Here is a comprehensive list of ready to go flight controller boards:

http://robot-kingdom.com/best-flight-controller-for-quadcopter-and-multicopter/

The AeroQuad MEGA Shield The AeroQuad board is a shield for the Arduino, either the Arduino UNO or the Arduino MEGA. The AeroQuad board requires the Sparkfun 9DOF stick which is soldered to the shield.

The ArduPilot board contains an ATMEGA328, the same as on the Arduino UNO. Like the AeroQuad shield this board doesn’t contain any sensors either. You would have to buy the ArduIMU and connect it to the board to use it.

The OpenPilot is a more advanced board which contains a 72MHz ARM Cortex-M3 processor, the STM32. The board also includes a 3-axis accelerometer and 3-axis gyroscope. Together with the board comes a great piece of software for the PC to calibrate, tune and especially set waypoints for your QuadCopter if you have installed a GPS module which I will be talking more about in the next section.

Make You Own Quadcopter Controller Board

Alternatively you can also use general purpose microcontroller, such as Arduino.

[Coming soon]

RC Transmitter

QuadCopters can be programmed and controlled in many different ways but the most common ones are by RC transmitter in either Rate (acrobatic) or Stable mode. The difference is the way the controller board interprets the orientations feedback together with your RC transmitter joysticks.

In Rate mode only the Gyroscope values are used to control the quadcopter. The joysticks on your RC transmitter are then used to control and set the desired rotation speed of the 3 axes, though if you release the joysticks it does not automatically re-balance. This is useful when doing acrobatics with your quadcopter as you can tilt it a bit to the right, release your joysticks, and then your quadcopter will keep that set position.

For the beginners the Rate mode might be too difficult, and you should start with the Stable mode. All the sensors are used to determine the quadcopters orientation in the stable mode. The speed of the 4 motors will be adjusted automatically and constantly to keep the quadcopter balanced. You control and change the angle of the quadcopter with any axis using the joystick. For example to go forward, you can simply tilt one of the joysticks to change the pitch angle of the quadcopter. When releasing the joystick, the angle will be reset and the quadcopter will be balanced again.

Check here for a more detailed RC transmitter article.

Optional Components

After buying all the necessary parts, and you are still not broke, you might consider other popular optional components such as GPS modules, ultrasonic sensors, barometers etc. They can enhance the performance of your quadcopter, and bring more features.

A GPS module talks to the satellite and retrieve accurate location information. We can use this information to calculate speed and path. It is especially useful for autonomous quadcopters which needs to know its exact position and which way to fly.

An ultrasonic sensor measures the distance to the ground, i.e. altitude. This is useful if you want to keep your quadcopter a certain distance from the ground without having to adjust the height it’s flying at constantly yourself. Most of these sensors has a range between 20cm to 7m.

When you gets higher, you might want to use a barometer. This sensor measures humidity and pressure to work out the altitude, so when the quadcopter is close to the ground (where these two factors doesn’t change much), it becomes ineffective. Therefore it is also common to use both of them at the same time.

Conclusion

Hopefully this article has given you a better understanding what each part of the quadcopter does, and how to go about selecting the right product for your quadcopter.

Please do not hesitate writing a comment or giving us some feedback on this article. The next post will be about the software side of the quadcopter.

If you are into FPV and Video taking, you might find this collection of FPV videos interesting.

How to choose Motor and Propeller for Quadcopter and Multicopter

motor propeller

You won’t believe how much maths and aerodynamics are involved when the engineers are designing the propellers and motors. Therefore you know how difficult it is to choose the best motor and propeller combination for your quadcopter for best performance.

Fortunately this is not a new subject, and there are so many people shared their experience about this. Also there are some general rules you can follow to choose the optimal and effective motor and propeller combination.

As part of the quadcopter tutorial I will share some information for beginners about how to choose motor and propeller for quadcopter, which also applies to other types of multicopter.

Some basic concepts when selecting Motors

brushless_motor_1

When selecting motors, there usually are specification that comes with the motor either provided by the seller or manufacturer. You should be able to find information about the power, thrust, rpm etc. This is an example of the 18-11 2000kv Micro Brushless Outrunner (10g) on Hobbyking.com. Google it if you are not sure what each name represents in the data sheet, they are really basic and I am not going to go over them here.

quadcopter motor data-sheet

quadcopter motor spec

To choose a motor we first need to how much weight you are planning to take, and then to work out the thrust required to lift the quadcopter. A general rule is that you should be able to provide twice as much thrust than the weight of the quad. If the thrust provided by the motors are too little, the quad will not respond well to your control, even has difficulties to take off. But if the thrust is too much, the quadcopter might become too agile and hard to control.

A rule of thumb is Required Thrust = ( Weight x 2 ) / 4

For example if we have a quadcopter witch the flying weight might be around 1 KG. Using the equation above, we now know we’re looking for a total thrust of 2 KG and 500g per motor. Of course you will have to guess the final weight of your quadcopter, when estimating, don’t forget to add the weight of the motors and propellers which vary. If you are thinking about FPV or aerophotography, you will need to add the weight of the camera as well.

Although you can choose the motors for the weight you want to carry, it’s always a good idea to carry as little weight as possible. Lightness is very important to all aircraft because any excess weight could reduce your battery life and maneuverability.

Some basic concepts when selecting Propellers

images

A quadcopter uses two clockwise(CW) and two counter-clockwise(CCW) propellers. Propellers are classified by length and pitch. For example 9×4.7 propellers are 9 inch long and has a pitch of 4.7.

Generally, increased propeller pitch and length will draw more current. Also the pitch can be defined as the travel distance of one single prop rotation. In a nutshell, higher pitch means slower rotation, but will increase your vehicle speed which also use more power.

propeller pitch

When deciding on length and pitch, you need to find a good balance. Generally a prop with low pitch numbers can generate more torque. The motors don’t need to work as hard so it pulls less current with this type of prop. If you want to do acrobatics, you will need torque propellers which provide more acceleration and it puts less pressure on the power system. Lower pitch propellers will also improve stability.

A higher pitch propeller moves greater amount of air, which could create turbulence and cause the aircraft to wobble during hovering. If you notice this with your quadcopter, try to choosing a lower pitched propeller.

When it comes to the length, propeller efficiency is closely related to the contact area of a prop with air, so a small increase in prop length will increase the propeller efficiency. (pretty much like swimmers with larger hands and feet can swim faster, but also more tiring for them)

A smaller prop is easier to stop or speed up while a larger prop takes longer to change speeds (inertia of movement). Smaller prop also means it draws less current, that is why hexacoptors and octocopters tend to use smaller props than quadcopter of similar size.

For larger quadcopters that carry payloads, large propellers and low-kv motors tend to work better. These have more rotational momentum, and will more easily maintain your aircraft’s stability.

Some tips on how to choose Motor and Propeller

There are two ways I usually do.

  • Observe and Research – go on to youtube and search people’s flying video, not only you can see the result of their quadcopters, you can also check out their setup, what motor and propeller they are using. It’s essential to learn from people’s experience because it’s free :-)
  • Understand the maths and Experiment – if you have a great mathematical mind and have spare budget, and could not find any information about the motor and propeller combination you want to use, you could experiment with different setups! Although it requires more money and more time.

Finally, there are some great quadcopter calculators on the internet that are designed specifically for multicopters. They might help you find the component combinations to maximize your quadcopter performance.

Conclusion

With a well balanced motor and propeller combination, your quadcopter should achieve great efficiency, not only improve battery life time, but also allows great user control experience. Hope this post has helped you select the best motor and propellers, and don’t hesitate to share your ideas or questions with us.:-)

How To Choose RC Transmitter For Quadcopter

Remote Controller Protocol

Before building your quadcopter, the RC Transmitter would probably be the first few things you need to look at. It’s a common question for RC beginners how to choose a decent RC transmitter. In this article I will discuss the basics of a RC transmitter and what you should buy.

Unlike other parts there isn’t much room for you to DIY, so it’s common that we would just buy a commercially available transmitter. There are a few things about functionality you should know before discussing the price.

Channels

You might already often hear the term Channel when talking about RC transmitters. Each channel allows one individual thing on the aircraft that can be controlled. For example, one channel for throttle, one channel for turning right and left, one channel for pitching forward and backward, one for rolling left and right. Four channels is a minimum for a quadcopter (pitch, roll, throttle, yaw).

RC-transmitter-channels

With more channels than just four, you can even have switch, or potentiometers to change settings on the quadcopter while flying. Some fly controllers (e.g. Multiwii, Arducopter) recommend using transmitters that has at least 5 channels, the extra channel is to switch between different flying modes.

5-channel-transmitter-diagram

Modes

There are 2 different Modes – mode one and mode two. It’s basically different control configuration.

The mode one configuration has the elevator control on the left joystick and the throttle on the right one.

The mode two is the most common for quadcopter because the stick represents the movement of your quadcopter. It has the elevator control on the right joystick and the motor throttle on the left one. The right joystick self centres in the both axis, whereas the left joystick only self centres in left/right axis and “clicks” in the up/down axis in order to allow the throttle setting.

transmitter-stick-modes

RC Transmitter and Receiver Paring

A receiver usually comes with the transmitter when you buy it. But be aware that some types of transmitter are only compatible to their own receivers (same brand same model). That means when the receiver is broken you will have to get the same one. There are a few exceptions that they can be paired with other receivers (i think universal is the word?). Make sure you check and ask the shop before buying.

What RC transmitter should I get?

The price range is huge, from as cheap as $20 to over $1000. Of course the cheaper, the lower quality it would be, and the fewer channels you are going to get. It would be a good idea to get a cheap 5 or 6 channel one to get a taste of flying a plane, and later one upgrade to a better transmitter when you know more about the subject. It’s always a good idea to have backup transmitters anyway. However if you are serious about quadcopters and someday want to get one with GPS navigation you will need 8 or more channels.

The transmitter is potentially a long term investment. If you are not sure about whether you will be staying in this hobby, you would be safe to get something like a cheap 6 channel. But if you are sure you will stay in the next couple of years you will not regret to get a 8 channel or more! Moreover It’s not just a matter of number of channels. Some RC transmitters support programming and firmware flashing to enhance functionality as well. So do your research before spending good money on it.

Recommedation on 8 Channel RC Controller

If you ask me that, I current favourite is the Turnigy 9X! See my review about this Transmitter.

DIY RC Transmitter

Although it’s possible to hack a game console and make your own RC transmitter, it seems quite difficult.

I actually also built a RC Transmitter myself although I haven’t tested it yet with a quadcopter.

Best Quadcopter For Beginners and Tips to Start Out

Posted on September 22, 2013 by 

best quadcopter expensive

A few people asked me What is the best quadcopter to start out for beginner. It’s a tricky question because there isn’t really a best quadcopter setup. The parts that put into the quadcopter would make the quadcopter feel different in terms of control-ability so it’s very much down to personal preference and ability. For example if you use a lighter frame you might have a more agile quadcopter but harder to control too.

Anyway I will share with you what would be a good route to take to start out with quadcopter and what options you have. If you have no RC flying experience in the past, you might find this post useful.

Research and Study

When I first got interested in Quadcopter I spent a few weeks watching reviews and guides. Hearing from people’s flying and quad-building experience really helped me to understand quadcopters.

So you won’t go wrong with too much research and study, and asking tons of questions on forums before you spend a lot of money on the parts, and only found out your quad doesn’t fly. Here are some good forums I go to quite often:

I put together a comprehensive guide explaining how each component works on a quadcopter you might also find useful.

If you have any questions, feel free to ask on this quadcopter message board.

The Best Quadcopter You Should Get To Start out

As a quadcopter or RC beginner, you are almost guaranteed to have countless crashes with your drone at the beginning. Even just once among those countless crashes is fatal, it will cost you money to replace broken parts! So practicing with a cheap quadcopter became important.

If you have enough budget, I would personally recommend getting a small mini quadcopter, but it’s totally up to you. After you have mastered the flying skills with this mini quad you can move onto bigger ones, or start building your own quadcopter. It gives you an opportunity to understand how to control a quadcopter, and trains your eye-hands coordination. I got one of those and they are just so robust and still flying after hundreds of crashes.

best quadcopter cheap mini one

Most of these mini quadcopters usually only have the most basic sensors (3-axis accelerometer and 3-axis gyro) which means it flies in a more manual mode. If you start with a super-stabilized platform, you may have trouble flying other quadcopter. The idea of your first quad is to get a couple hours of flight time in so that your brain and your muscle memory start knowing how to fly. It’s like driving cars really! Driving a cheap and shit car when you are just learning how to drive, isn’t always a bad idea :-)

How to Start with Flying Technique?

This is how I learned to fly. It’s important to start your practice by standing behind the quadcopter so you are facing the same direction as the quad. This will allow the movements on your transmitter to make the quadcopter go in the same direction as you push!

Hovering

You’ll want to lift your quad off the ground almost instantly to around 1 meter (3 foot). Because when it’s too close to the ground you might get air disturbance from the motors (ground effect). Just try to hover around the same spot with the same height using throttle, pitch and roll.

Landing

If Hovering isn’t too difficult for you, you can now try mastering landing. It sounds easy but it’s one of the most important technique beginners seem to forget. The idea here is the throttle control, remember to loose it really slowly and smoothly. Do not cut the power instantly, your quad will free fall and might damage your frame or electronics.

Pitch and Roll Control

Pick a location you want to go to, use pitch and roll fly to that spot and land.

Yaw Wondering

This one is a bit like those soccer player practicing ball-control around the poles. You will only use pitch to go forward  and use Yaw to turn left and right. You can either practice flying in circle, or in the shape of “8″. This control technique is very useful when you start FPV, or taking videos in the sky.

Other Best First Quadcopter

A lot of people take the hard way and build large quadcopters as their first quad. If you don’t have spare budget for a mini quad, this seems to be the only way to go. But again, if you crash badly due to lack of control practice, it might cost you more eventually (speaking from personal experience). You might even hurt someone if you lost control. This thread on RC Group might also be helpful to you.

Palm-size Mini Quadcopter Hardware Settings

Posted on September 14, 2013 by 

Mini Quadcopter Hardware settings

Here is a really small quadcopter that uses Arduino and Brushless motors Built by Bob. I will mainly describe the parts and hardware you will need to build this mini quadcopter, and I will not go into flight controller configurations, software and programming etc. There are many options out there. I will do another post about this.

This little Arduino quadcopter is an brilliant design and is runs very quite. Because of its small size, this little quadcopter is perfect for indoor flying.

ere are the parts used to build this mini quadcopter.

As for propellers, some cheap 5x3x3 props (2 CW and 2 CCW) are used. The Hobby King 5×3 and 5x3R aren’t very good. They do work, but it takes a long time to balance them, and sometimes the mounting hole is not centered.

Anyway, from the picture you can see it uses Arduino Pro Mini as the flight controller.  There are a lot of opensource quadcopter library for Arduino, such as MultiWii. Therefore unlike KK flight controller boards, you will need to equipped your Arduino with IMU. But the good thing about this is, you can add whatever components and modules you want to the Arduino, such as bluetooth, for iPhone / Android control.

Arduino Nano Quadcopter Hardware Setting

Posted on September 14, 2013 by 

Arduino Nano Quadcopter using razor IMU 6DOF

Here are some pictures guide you through how to make an Arduino Nano Quadcopter by Wov. It uses Arduino Nano as the micro-processor and Razor 6DOF IMU. There won’t be any source code available as it uses Aeroquad. If you want to learn how a quadcopter works, check it out.

The PCB is home-made, it has voltage converter to lower the 5V voltage to 3.3V for the Razor IMU.

The motors are light-weight 18/11 2000kV Outrunners. ESCs are Turnigy Plush 6A. Propellers would be the small 3 bladed GWS 6×3 propellers. The frame is only 25cm diagonally.

The Software Configurator is simply great and so easy to use. There is also a 3D design of the Arduino quadcopter.

Arduino Multiwii Quadcopter Connection Test

Posted on September 17, 2013 by 

Arduino Multiwii

Today I loaded up the Arduino Multiwii Quadcopter code on the Arduino Uno, and connected everything including  a Radio controller, the IMU, ESC and motors, it works straight away! It’s so much easier than I thought.

The reason I am using the Arduino as a flight controller was my KK2.0 was totally damaged in the last crash. Luckily everything else apart from the flight controller and frame is fine!

Arduino Multiwii kk2.0

So I decided rather than buying a new flight controller, I might try to dig out a spare Arduino board to make one myself. Since there are already so many open source Arduino projects for quadcopter, it’s not difficult at all to setup one. It’s not a new thing at all, and they are very well documented as well. But since building a quadcopter isn’t a straight-forward task, it does take time and effort to read and learn things.

I basically followed this diagram from the Arduino Multiwii website  to connect everything.

quadcopter multiwii connection diagram

Here is the result.

for more detail go here: http://aeroquad.com/showthread.php?253-Mini-Aeroquad-with-Arduino-Nano-V3-and-Razor-6DOF

Arduino Nano Quadcopter 3D model

Arduino Nano Quadcopter all parts

Arduino Nano Quadcopter PCB

Arduino Nano Quadcopter control unit

small Arduino Nano Quadcopter

Multiwii Loaded Arduino Nano Quadcopter Take Off Testing

Posted on October 8, 2013 by 

IMAG0967

After the arduino connection testing, all the parts seem working fine (IMU, arduino, receiver, ESC and motor). So the next step is to try to do a take off test. I need to build a flight controller adapter to sit all the electronics on it (IMU, Arduino etc), which can also cut down the number of cables I need to connect the ESCs and receiver. But I wanted to make sure the system works (can take off) before I spent time doing it, so I keep everything on a breadboard to carry out the test.

Issue – Quadcopter flips on take off

But it didn’t work! It just keeps flipping on take off. There were a few things I know which might cause this:

  • Sensor (Gyro + Acc) not calibrated correctly – need to place on a plat and level surface and calibrate first.
  • Sensor Orientation might be wrong? e.g. upside down or wrong way round, you can check this in the GUI.
  • Calibrate ESCs
  • Propellers are not the right size. Generally the manufacturer should recommend the appropriate prop for the motors. You need larger props with fewer cell battery.
  • Make sure the motors are connected in the right order, and props are rotating in the right direction.

To Calibrate ESCs:

its in config.h here is the procedure and please please please pay attention to the first detail

1.REMOVE YOUR PROPS FIRST
2. open the sketch in arduino IDE, uncomment //#define ESC_CALIB_CANNOT_FLY 
3. upload the sketch to your flight controller.
4. remove the usb/ftdi cable and all power from your flight controller, then attach your battery
5. listen for the beeps stating that calibration is being performed (my beeps several times, plays a chime song, then gets quiet)
6. remove power, then reconnect your ftdi/usb cable
7. open the sketch in arduino, re add the // to #define ESC_CALIB_CANNOT_FLY 
8 reload the sketch as it was prior to the calibration.

you are now complete. 

what did this do? (for anyone reading this who hasn't dealt with ESC's and multiwii long)

this is the best way to make sure that the upper and lower limits of your speed controllers are exactly the same on every motor on your copter. if they are not, the software will have difficulty maintaining stable flight, even when hovering.

Solution!

I couldn’t find the cause of this problem, so I build the adapter anyway, it might be the sensor is not fixed in position and shakes when motors are rotating. I describe how it’s built here.

Later on I found that when I turn on throttle (only a little so it stays on the ground), the sound from the motors on one side is getting louder even though I am not increasing throttle, and eventually it gets to a point where it flips.

I realized it’s the motors are the wrong way around! so I swapped the diagonal motors around, and everything works as expected.

Some questions during research

Should I connect all BEC Vcc and Gnd together in parallel? 

NO! http://www.rcgroups.com/forums/showthread.php?t=1126572&page=7

How to connect ESC and motor (when all the cables have the same color?

It dosent matter what order. If the motor spins the wrong way after your done just swap any two wires and the motor will spin in the other direction.

what the maximum number of channels supported by Multiwii?

Four base channels (throttle, yaw, roll, pitch) and 2 aux (mode and something else).

Two: AUX 1 on “MODE” and AUX 2 on “D8″ or “D12″. You have possibility to use PIN8 or PIN12 as the AUX2 RC input. It deactivates in this case the POWER PIN (pin 12) or the BUZZER PIN (pin 8)

For AUX 2 uncomment into config.h one of the two lines:// #define RCAUXPIN8 or //#define RCAUXPIN12

Conclusion

There are still works to do with the PID value tuning.

Arduino Simulators Review – Free Virtual Circuit To Test Your Ideas

Posted on September 23, 2013 by 

arduino simulator iphone

Why do you need a Arduino Simulator?

Arduino is a great platform to get people start learning programming and designing circuits. But inevitably beginners might do something wrong and damage components. Also for students budget is always a problem when it comes to buying new electronic parts, and you have no idea if it’s going to work until you spend money on it! Arduino Simulator provides a solution to these problems, no damage done to your components, no money spend on hardware, faster circuit prototyping and no mess with cabling at all! :-) Some Simulators even allow line to line debugging, so you know exactly which line goes wrong.

There are many available Arduino Simulators, exist in free or paid versions, based on Linux, Windows, Mac OS. I will list them here and provide information on the price and supported OS. If you have come across any good ones I missed here please comment and let me know.

Although it’s useful to have an Arduino Simulator, it’s important that you fully test your circuit on the physical hardware as well. Because there are situations where the physical world cannot be fully, perfectly simulated by the software.

List of Arduino Simulators

I have to say, a lot of these Arduino Simulator authors need to be more creative with the names! most of them are called “Arduino Simulator”! and I have to differentiate them by the platform! (only joking :-) , it’s great that you guys created these awesome apps for everyone! – only if it’s free and open source)

1. Open Source Arduino Simulator

Free? Yes

OS: Windows

Link: https://github.com/Paulware/ArduinoDebugger/

For tutorial videos, someone is kind enough to post them all in one page.

arduino simulator

2. Arduino Simulator on iPhone / iPad

Free? No

OS: iOS

Link: http://schogini.in/app-websites/arduino-simulator/

I have not tested it but from the videos, it looks quite rich in terms of components and well documented. But you obviously can’t use this tool if you don’t have an iPhone. However they only scored 2 in the app store review, so read reviews before you spend money.

3. ArduinoSim

Free? Yes!

OS: Windows, Linux

Link: http://arduinosim.sourceforge.net/

4. Simduino

Free? Yes!

OS: Windows

Link: http://code.google.com/p/simuino/downloads/list

5. Arduino Simulator on PC

Free? No

OS: Windows, Linux

Link: http://www.virtronics.com.au/Simulator-for-Arduino.html

There is a hardware options menu that lets you select the type of Arduino you want to use – Due, Leonardo, Mega or Nano. You can also use an LCD display. However you cannot add custom hardware and shield. So you are pretty limited in terms of choice of components.

arduino-simulator

6. Emulare

Free? Yes!

OS: Windows and Linux

Link: http://emulare.sourceforge.net/download.php

This seems to have the longest development period of all the simulators I have seen (since early 2010). A good feature of it is allowing users to simulate multiple Arduino’s at the same time.

Conclusion

[mrburnette] on this thread made a very good point about paid arduino simulator.

At this point, I do not personally think that most Arduino users will benefit from non-free tools.  And professional developers are likely using professional tools for AVR and programming outside the confines if Wiring.  There is a tremendous benefit for the new programmer-maker to THINK their way through issues without throwing money and new toolsets toward the problem. 

Xbee Alternative XRF Wireless RF Radio Module And Arduino

Posted on July 11, 2013 by 

remote-XRF-to-Arduino-connections 8

In this post I will show you how to connect the XRF with Arduino, and will show you a example application with two Arduinos talking to each other using the XRF wireless module.

Bought The XRF Wireless RF Radio Modules

As part of the DIY Custom Remote Control, I will be using wireless modules for remote communication. There isn’t much choice, either Radio Transceiver or Xbee. Both are great but quite expensive. Later on I stumble on an cheaper Xbee Alternative called XRF Wireless RF Radio Module, that claims it has the same pin configuration as the Xbee, the way it’s used is also the same, and the range can reach up to 1 Km (although some feedbacks said it’s more like 300m but it’s still great). More importantly, it’s only half of the price of a Xbee module.

I think the main difference is that this module transmits data at lower frequency (868 and 915 MHz) than the Xbee (2.4G Hz), and that partly explains why the transmit distance is longer.

Problems Right Away

remote-XRF-to-Arduino-connections 9

I bought the break out boards (XBBO) with wireless modules too, and I only found out that the ones I bought are called “Passive XBBO” which doesn’t accept 5V power supply but only 3.3V (not 5V signal as well because of that). Only “Active XBBO” would accept 5V and convert the voltage for you. I didn’t notice that when purchasing (should have been more careful and read the description), So, it didn’t work when I just simply connect everything. My first thought was the TX/RX data line voltage on the Arduino is too large (5V) for the XRF (3.3V).

I tried so hard searching on Google, there isn’t much information about this, even not much about the XRF module working with Arduino. So I decided to take the risk by following tutorials about the Xbee, since they are similar devices, and it did work!

A Not-So-Perfect Solution

I found this image about Xbee and arduino:

remote-XRF-to-Arduino-connections1

I noticed the potential divider on it and I thought, that this might be it! Because on the break out board, we have already have the capacitor, so we can ignore that (it still works without it anyway).

I don’t have any 15K resistors, so I am using a 4.7K in series with a 10K resistor. (Ignore the LEDs and the blue resistors, I was too lazy to remove them from the last project).

remote-XRF-to-Arduino-connections2

IMAG0711

Okay, it’s great that it works finally. But it’s kind of annoying having to setup the potential divider every time. So I made a small strip board with the potential divider soldered on, and it also has a female to female connection, so it’s easier to work with as well with the Arduino.

remote-XRF-to-Arduino-connections 6

Here is the new result:

remote-XRF-to-Arduino-connections 4

remote-XRF-to-Arduino-connections 7

remote-XRF-to-Arduino-connections 5

Although it’s cheap and easy enough to work around it, but I still would suggest to get a proper break out board with voltage conversion and additional functionality like power and data transmission indication.

Two XRF and Arduino Test Application

To verify they are working, I made this test application. There are two Arduino involved, both will be using the XRF modules to send and receive data. Arduino1 will be sending data – 0, 1, 2, 3, 4…. 8, 9, with an interval of one second. Arduino2 will receive these data, when received data is 1, the LED on pin13 (built-in LED) will light up for one second and then goes off, otherwise nothing will happen.

So in theory if everything is working, we should see the LED on Arduino2 light up every 10 seconds

Code For the Sender – Arduino1

1 int num = 0;
2
3 void setup(){
4     // start serial port at 9600 bps:
5     Serial.begin(9600);
6     pinMode(13, OUTPUT);
7
8 }
9
10 void loop(){
11     if (num++ >= 9)
12         num = 0;
13     delay(1000);
14
15     Serial.write(num);
16 }

Code For the Receiver- Arduino2

1 int num;
2
3 void setup()
4 {
5     // start serial port at 9600 bps:
6     Serial.begin(9600);
7     pinMode(13, OUTPUT);
8
9 }
10
11 void loop(){
12     if (Serial.available() > 0) {
13
14         // get incoming byte:
15         num = Serial.read();
16
17         if(num == 1){
18             digitalWrite(13, HIGH);   // set the LED on
19             delay(1000);              // wait for a second
20             digitalWrite(13, LOW);    // set the LED off
21         }
22
23     }
24 }

DIY Wireless RC Remote Controller for Robots, Quadcopter

remote_controller_feature

Great robots deserve a great remote controller. A proper, well designed controller can speed up project development and in some cases can even improve robot performance. In this post I will describe how I design, make, test and improve a customized RC remote controller.

I call this project “Omote” – Oscar’s Remote controller. (Just to clarify, it has nothing to do with the Japanese word Omote which in Aikido, it could mean the act of throwing your opponent in front of them, thanks to John Matsson pointed that out, haha)

The Omote Goal!

The goal of this project is to create a remote controller that can be alternative to a RC transmitter or similar commercial controllers. The remote controller we build would be able to control, manipulate our robots, flying planes like quadcopter, even can be used for PC gaming like car racing games. There are quite a lot of existing commercial controllers like RC transmitters, but they tend to be very expensive and probably not optimized to the project we are doing.

We are going to focus on

  • affordable
  • customization
  • multi-purpose
  • latency
  • accuracy
  • reliability
  • operation distance
  • informative

This is the final product. It’s not perfect, and I learned a lot from this trial version. So I might think about making an new version when I have time.

DIY Customized Remote Controller_front

I will divide this project into these tasks. And hopefully at the end we will have a reliable working remote controller.

This is the LED and Servo Control Demo video:

Remote Controller Hardware And Electronics

I tried to use parts that are as simple and cheap as possible. But what components to pick largely depend on what kind of project or robot you are trying to control. For example for a simple robotic tank, you might want to be able to make it go forward and backward, turn left and right. So four push buttons would be enough to accomplish this. But if you want to have better user experience, a joystick would be better. If there is a canon on the tank, you probably also want a button for shooting. If there is a head light, you will need a toggle switch. You should see where this is going.

DIY Customized Remote Controller_design

For my remote controller, I am not designing it narrowly for some particular projects, but for more general usage. Therefore I used a combination of different types of control components. This is what it looks like on drawing.

Here are the parts I used:

  • Toggle Switch x 4
  • 2-Axis Joystick x 2
  • Potentio Meter x 4
  • Push Button x 6
  • LED x 3
  • LCD x 1
  • Arduino Mega x 1
  • Cables x many
  • Small Breadboard x 2
  • Ciesco XRF Wireless Modules x 2

For the Wireless communication Modules, I chose to use the Ciesco XRF because they are so much cheaper than the XBee. I wrote a post on how to use them, check it out it’s very straight-forward. Xbee would also work.

I picked the Arduino Mega because I know Arduino very well. The Mega provides more enough Analogue and Digital pins, which the UNO failed.

I was thinking of getting a 3 Axis Joystick, but they are shockingly expensive! The cheapest one I found was 30 Euros which is literally just a 2 axis joystick with a potentiometer. So I went for the cheap option of getting these two parts separately and it costs me only 3 pounds.

Inputs of These Components

Toggle Switch, Push Buttons return true when pressed (1) and false when it’s not (0). Potentiometer has a max resistance of 10K which give a value between 0 to 1023. 2-axis joysticks are basically just two potentiometers, which gives you two values between 0 to 1023 for X and Y axis. It might be a good idea to test and make sure you understand how these components work before doing any further. The picture shows the testing setup I had.

DIY Customized Remote Controller_hardware_testing

Soldering and Assembling

Assembling wasn’t particularly difficult as everything went quite smoothly as planned, though I had to turn some parts around to fit the actual dimension. Here are some soldering work I did on the parts:

DIY Customized Remote Controller

DIY Customized Remote Controller_push_buttons

DIY Customized Remote Controller_joystick

DIY Customized Remote Controller_potentiometer

Male to Female cable made by myself, they are very handy to have.

DIY Customized Remote Controller_cable3

DIY Customized Remote Controller_cable2

The Arduino Mega is attached to the base board. And the white front panel finished using Polystyrene.

DIY Customized Remote Controller_arduino mega

DIY Customized Remote Controller_panel

This is what happened when I put every components on the panel, it’s a mess! But when I turned it over, I felt much better, LOL.

DIY Customized Remote Controller_messy cable

DIY Customized Remote Controller_all most

It took me about 2 to 3 hours to finish the final hardware testing after the assembling. And that’s it! All the parts are working and ready for programming!

DIY Customized Remote Controller_side

DIY Customized Remote Controller_done

Some Assembling Advice

Make sure you have all sorts of jumper cables ready: Female to male, male to male and female to female. And make sure they are long enough, generally you want them to be twice as long as the width of your remote controller, so you can have the panel and base laid down naturally side by side  while you are connecting the components. Otherwise you will have a really painful time doing that. For trouble shooting, it’s even worse when short cables are used.

Carry out testing right after you connect a component. It would be a nightmare to have all the parts connected and realize nothing works!

Software Overview

Software for this project consists two parts, one for the remote controller (which I call “Host” later on), and the other for the robot (“Client”).

As for software for the remote controller, the idea is quite simple (see state flow chart). But I can foresee to achieve what is required, the programming can get very sticky and complicated. It is responsible for initializing connection, re-establishing broken connection, encoding commands and provide feedback from client to the user. There will also be a LCD menu system to provide current state information of the controller, allow real time parameter adjustment, calibration and so on.

DIY Customized Remote Controller_host

On the client side (robot side), I will be writing a library for it which will act as an interface between the robot and the controller. It is responsible for accepting connection, decoding commands and communicating back.

DIY Customized Remote Controller_client

Arduino Function For Fundemental Communication

As for sending data, because we are using the serial pins on the Arduino, I will be using Serial.write() for sending data. This function sends one byte of data which means the max value we can transmit is 255 each time we call this function.

You might be wondering what we should do about the inputs from the potentiometers and joysticks, as they have a max value of 1023. We have two options, one is to downgrade resolution to map the value between 0 and 1023 to a new value between 0 and 255, which can be fit in one byte. Second option is to treat the number in term of bits (1024 can be represented with 10 bits), which can be send separately as two packets. When they arrived at the client side, we put them back together as one number.

As you might know, for a single value, sending two bytes would take longer than one byte. Although it’s less accurate, we sometimes don’t need that level of accuracy and prefer smaller latency. So I am planning to adopt both methods into the remote controller communication, so user can select which way to go depends on the situation.

And that takes us into the next section – the protocol. How do we design and put together a command from these raw input values for transmission? It’s going to be a wordy topic, so I will talk about this in the next post.

Robotic Remote Controller Protocol Design

Remote Controller Protocol

The Communication Protocol

Remote Controller Protocol design is the core part of the DIY Remote Controller Project, which can also be the most difficult part if you are aiming for a sophisticated design. I have had similar design experience in my past project designing communication protocol.

The protocol I am talking about is the format of a series of values we send from the remote controller to the client, each value is one byte packet sent using Serial.write(). I also call this series of values “command” and it looks something like this:

   1      122       93       28       19        1       0        1
| type | value1 | value2 | value3 | value4 | value5 | value6 | value7 |

“Type” is the type of protocol. I am going to design various type of protocols, each type uses different control values and precisions. The “Type” number tells the client how many and what kind of value we are expecting, and how to use these values.

This is a demo video using the protocol, controlling a quadruped robot.

A Trick To Encode Button/Toggle States

Since the buttons and toggles states only have values of 0 or 1 (boolean value), so it would not be very wise to transfer each of the input using a full byte. What I have done is to treat each button/toggle as 1 bit, and I have 8 of them so it’s just enough to make 1 byte (8 bits). That way I can save 7 bytes each time I send a command! I call this process of converting Button States “Button States Encoding”. When it reaches the client side, we have to do the reverse process to convert 1 byte value into 8 boolean values, and I call it “Button States Decoding”.

Button States Encoding

This is an example on how it works. Imagine we align the inputs like this

 | toggle1 | toggle2 | toggle3 | toggle4 | button1 | button2 | button3 | button4 |

(1) If Button3 is pressed and not any others, we have 0000 0010 in binary, which is 2 in decimal, and that’s the number we are going to send using this Serial.write(2);
(2) Another example if Toggle2 is on, and button2 is pressed and not others, we have 01000100, which is 2^6 + 2^2 = 64 + 4 = 68.

Notice the maths (+ additions and ^ powers) we have to do when doing the button encodings, this is quite computationally expensive. To improve this, we can manipulate what we call “Bit Shift Operator“. It can help reduce calculation time.

For example (1), we can now do button3 << 1, which is 2
For example (2), toggle2 << 6 + button2 << 2 = 68

1 // convert 4 toggle and 4 buttons state into binary, and then convert binary to byte number for transmission
2 // expect bit1 - bit8 are zeros or ones
3 byte EncodeButton(bool bit1, bool bit2, bool bit3, bool bit4, bool bit5, boolbit6, bool bit7, bool bit8){
4
5     byte sum = 0;
6     sum += bit1 << 7;
7     sum += bit2 << 6;
8     sum += bit3 << 5;
9     sum += bit4 << 4;
10     sum += bit5 << 3;
11     sum += bit6 << 2;
12     sum += bit7 << 1;
13     sum += bit8 << 0;
14
15     return sum;
16
17 }

Button States Decoding

To do the reverse at the client side, we need to test each bit of the received byte value to see if they are 0 or 1 and assign it to a variable that represents each button. Or you can also have a switch case statement to look it up, it’s up to you. From above examples:

(1) If we received 2, we need to check each bit start from most significant bit. Assuming Toggle1 is on, we should have received a value 10000000 = 2^7 = 128. But 2/128 < 1 thus Toggle1 = 0. Just like this, we work all the way down to Button3.

Assume Button3 is pressed, we should have 00000010 = 2, 2/2 >= 1, thus button3 = 1 is true!
Assume Button4 is pressed, we should have 00000001 = 1, (2-2)/2 < 1, thus button4 = 0!
So, all variables are 0′s, except button3.

Again, like Button Encoding, we can explode the “Bit Shift Operator” trick. From the above example, we need to test each bit starting from the most significant bit.
We received 2, 2 >> 7 = 0, thus toggle1 = 0; And work your way down.
2 >> 1 >= 1, so button3 = 1, (2-2) >> 0 < 1, thus button4 = 0;

1 void DecodeButton(byte byte1, bool *bit1, bool *bit2, bool *bit3, bool *bit4,bool *bit5, bool *bit6, bool *bit7, bool *bit8){
2 // Usage: DecodeButton(buttonByte, &toggle1, &toggle2, &toggle3, &toggle4, &button3, &button4, &button5, &button6);
3     byte sum = 0;
4
5     *bit1 = byte1 >> 7;
6
7     sum += (*bit1)*128;
8     *bit2 = (byte1-sum) >> 6;
9
10     sum += (*bit2)*64;
11     *bit3 = byte1-sum >> 5;
12
13     sum += (*bit3)*32;
14     *bit4 = byte1-sum >> 4;
15
16     sum += (*bit4)*16;
17     *bit5 = byte1-sum >> 3;
18
19     sum += (*bit5)*8;
20     *bit6 = byte1-sum >> 2;
21
22     sum += (*bit6)*4;
23     *bit7 = byte1-sum >> 1;
24
25     sum += (*bit7)*2;
26     *bit8 = byte1-sum >> 0;
27
28 }

Types of Remote Controller Protocols

As I have discussed in the last post, we are going to have multiple protocols that transmit data in different format and level of accuracy, so users are backed by these choices of different protocols depend on the situation. Sometimes you might want the smallest latency protocol (less accurate but faster transmission), and sometimes you might prefer high resolution commands (high accuracy but slower transmission). At the moment I have implemented these protocols, these examples give you an idea what the commands look loke.

1. All Controls, Short Version

All the values are made up as an example. Each value is a byte which has a max value of 255. Same applies to all four examples.

   0     122     93    28     19     60     55    199   250      50
| type | pot1 | pot2| pot3 | pot4 | js1x | js1y| js2x | js2y | buttons |

2. All Controls, Long Version (full accuracy)

    0         2           93           0           19           3
| type | pot1(high) | pot1(low) | pot2(high) | pot2(low) | pot3(high)
     0           155          1           155           3          0
| pot3(low) | pot4(high) | pot4(low) | js1x(high) | js1x(low) | js1y(high)
      3          51            1           12           25         21
| js1y(low) | js2x(high) | js2x(low) | js2y(high) | js2y(low) | buttons |

3. Selected Controls, Short Version

For this example, I selected a potentiomete, a joystick and all buttons and toggles.

   0     129     93     0        19
| type | pot1 | js1x | js1y | buttons |

4. Selected Controls, Long Version (full accuracy)

For this example, I selected a potentiomete, a joystick and all buttons and toggles.

   
   0      2          93         0        19       3       20         0 
|type| pot1(high)| pot1(low)| js1x(h)| js1x(l)| js1y(h)| js1y(l)| buttons

Channel

The term “channel” is used quite a lot when it comes to commercial RC transmitters. Channel can mean 2 totally different things:

1. the number of “things” you can control, for example for a joystick you need at least 2 channel, one for left right, one for up down (1 Degree of freedom each channel).
2. the number of different transmission frequency you can use to avoid conflicts with other remote controllers. (pretty much like Radio channels)

Remote Controller Protocol

Fortunately none of these would be relevant to my remote controller. For (1), because the way I send data, I can choose to send input data from each control one by one if I want, so no matter how many thing I need to control, it would be do-able (although the more control means more data to transmit thus takes longer). For (2), I can use something called “controller identifier” in the command I send to differentiate different controllers, so the commands will only be picked up at the client side with the pre-defined identifier. This is only an idea but totally do-able.

Visual Basic Arduino Controlled Through USB

arduino_uno_test

Visual Basic Arduino. So, Why?

When we are debugging and testing our circuits and codings, most of the times we reset the Arduino board and upload the new program. But the thing is everything has a finite lifetime, and by doing harmful things to the body would even reduce life quicker. Visual Basic Arduino.

Just like smoking could kill you, repetitively uploading could kill your arduino too! I still remember I read from somewhere, and someone said an Arduino board has an average uploading limit of about 1000 times… I don’t know if this is true, but if we could avoid doing something that could harm the arduino, then why not?

So here we are, I was looking for a way to test and develop new moves and gaits for my hexapod robot. But frequently uploading new codes really cost me time and risking killing the arduino, so I thought it would be nice to test it just by sending the arduino a command through USB connection (Serial communication), therefore the possibility of program uploading could be minimized.

Updates

1/1/2012

Happy new year!
I will divide this tutorial into 2 sections: Receiver and Sender ends.

Receiver side coding:

So the command I designed would look like this.
MxPxDx/

x – arbitrary number
M – mode (0 – write, 1 – read, 2 – servo control)
P – pin (0 – 13), or servo number (specified in arduino program)
D – data (0 – LOW, 1 – HIGH, or (600 to 2400) – servo position)
/ – indicate end of command (to execute)

for example,
M0P2D0/ – means to make pin 2 LOW
M2P1D900/ – means to make servo number 1 to 900 ms (1500 = 90 degree)

The idea is that the command get sent to the arduino as a array of charaters one by one, which has delay between each charaters.
notice that the function Serial.read() can only read one byte (one charater) at a time. So if you write something like this:

a = Serial.read()
b = Serial.read()

you can get the first character, but the second one might not be read as it hasn’t arrived at the serial receiving buffer yet.
So I use this statement:

void loop(){

if (if (Serial.available() > 0) {

//…Read one byte and store in array…

//…if the last character read was ‘/’ then…
//…execute the command…

//… reset the command array, …
//…keep listening to serial port…

}

}

Serial.available() indicates how many bytes are available to be read. So the arduino just keeps running, and reads data when it becomes available and that’s how commands are received. Here is how the command is decoded and executed:

1. When I received a character ‘M’, I remember all the char after ‘M’, before I encounter ‘P’, and store that in variable ‘mode’
2. same, store characters after ‘P’ and before ‘D’, in variable ‘pin’
3. store characters before ‘/’, in variable ‘data’

Then convert these char into int type (you can also do it during above process), by subtracting ’0′, which has an ASCII value of 48.
So now we have 3 variables, which is basically the commands. To execute the command, we can write something like this:

switch (mode){

case 0:
digitalWrite(pin,data);
break;

case 1:
//…Read digital pin…
// … Read analogue pin…
break;

case 2:
// …Control Servo…
// … set position, read position so on…
break;

}

To execute read and servo commands, we will need more complicated coding, but that’s roughly how it would work.

Sender side Coding:

To use this serial command system, no coding is needed when using arduino serial monitor. just type in the command and it just works!

But that isn’t even 5% of the amazing things it could achieve! If you could write a program and introduce graphical interface, controlling the arduino would be so intuitive and clear! also command can be sent more rapidly through computer programs, especially useful when testing robot moves, or LED lighting effects!

I think the most popular choices for serial programming would be Python, C/C++, or Basic. I know C/C++ the best here, but the thing is C/C++ is not easy to write the graphical interface. So I went for Basic, which I realized its simplicity and fast development time. I spent 2 hours learning the basics, and got my program working 3,4 hours later. Surely most of us could do better.

In the example video (the LED control program), when the ON/OFF button is pressed, it goes to a ‘switch – case’ statement, depending on what LED is selected, corresponding LED is switched on or off. The Display function is even easier. it sends out a command, delay for sometime, before sends out another one. So the LED flashes and creates some kind of fabulous visual effect.

That’s it for the basics. I will carry on completing the code, especially the servo control for my hexapod robot. Finally will put it in a header file.

=====================================================
02/01/2012

Servo Control coding:

Receiver Side (arduino):

command example:
M2P0D1500/ ——— set servo number 1 to middle position (1500 ms).

This command works the best with my way of updating servos’ positions (described here, search for “26/12/2011″ update. )

Basically what it does is, there is a variable for the position of each servo, when command is received and executed, the variable will be updated rather than writing the servo position straight away. The position is only written at the end of the loop process (or when the timer has reach certain point if you want delay).

for example:

1 void loop(){
2
3   // ... command receiving
4   // ... command executing (update servo position and store in variable 'pos')
5
6   servo.writeMicroseconds(pos);
7
8 }

So in the execution coding block, we add:

1 // ============ Execute command ======
2    switch (mode){
3      case 0:
4        digitalWrite(pin,data);
5        break;
6
7      case 1:
8        digitalRead(pin);
9        break;
10
11      case 2:
12        switch (pin){
13          case 0:
14            pos0 = data; //
15            break;
16          case 1:
17            //pos1 = data;
18            break;
19          case 2:
20            //pos2 = data;
21            break;
22
23        }
24        break;
25
26    }

Sender side:

When we are testing using arduino serial monitor, no coding is needed.

In VB (basic), it’s best to use track bar.

Create events when trackbar is scrolled, this is an example

1 Private Sub TrackBar1_Scroll(ByVal sender As System.ObjectByVal AsSystem.EventArgs) Handles TrackBar1.Scroll
2
3     Dim valueInStr As String CStr(TrackBar1.Value)
4     Dim command As String "M2P0D" + valueInStr + "/"
5
6     SerialPort1.Write(command)
7     LB_ServoPos.Text = valueInStr
8
9     System.Threading.Thread.Sleep(100)
10
11 End Sub

it works when you only have one servo, if there are more servos need to be deal with, has to write more codes to determine ‘P’ (which servo to control).

================================================================

03/01/2012

Tested the serial command system, one big drawback is that between each command, the delay is quite obvious. When I intend to move 2 servo positions at the at same, one servo is actually moving before the other.

That’s because it uses this algorithm:

(waiting and listening to USB) —> (receive command 1) –> (Execute command 1) –> (waiting and listening to USB) —> (receive command 2) —> (Execute command 2) —>…….

Although command 1 and 2 are intended to be executed at the same time (sent at the same time), there will be a delay.

I re-consider the system, decided to fix this synchronization problem by adding an additional command:

SxCa…SyCb/

which contains all the servos and changes of position at the same time, and execute them all together, so delay could be reduced between servo moves.

The length of this command is indefinite, but can be determined by how many servos wants to be controlled. E.g. max length of command = (1+2+1+4)*number of servos

assuming we control 18 servos at most, the command buffer length would be 8*18 = 144 (this can be modified easily when needed)

for example:
S0C-200S4C600/ — would turn Servo 0 backward 200us, Servo 4 forward 600us.

You might notice, when 2 or more servos are moved at the same time, if the changes of positions are different, it will also result in a different duration (where some servo reach destination faster than others).

To address this, I added one more string of data at the end of the new command,

Lxxx,

which means Loops, or steps, required to finish transition. So ideally, when we have a command like the example above, “S0C-200S4C600L50/” Servo 0 will have to spend 50 loops in the arduino program to finish the transition, which divides servo 0 to move -4 each loop, and servo 4 to move 12.

You might think it’s unnecessary, but one big good thing it brings is smoothness! let image you want to change a servo position from 1500 to 800, you could do it at once (within 1 loop), but it introduces instability to your robot and circuit (draw of current). Also when motion gets too big, it won’t look pretty. with additional loop control, big motion can be broken down into small, digestible pieces.

Now we have the final template servo command:

SxCa…SyCbLc/

————————————————–
As we have a new command, additional algorithm in the arduino programm will be needed to code with it. What I will do is:

1. create a function that generate a new position for each servo at each loop.

2. make arduino to talk back! Sending the computer a signal, when we have complete a command, and available for another one. (so we can have a collection of commands waiting on the PC side, and are sent when arduino finishes the last one)

====================================================
05/01/2012

This will be the final update on this topic.

new idea of the command analysis process:

first of all we need to have a fixed length of command, by making unused its zero, and use ’1′ to represent negative in servo command e.g.

M00P05D0235/ — write pin 5 a PWM value of 235
S10C00300S02C10700L0100/ — turn servo 10 300um, turn servo 2 -700um after 100loops

in which case, instead of having a switch, we can now just loop through the command buffer char by char, to store the variables and data.

I want to do this is because

1. cleaner code block
2. less likely to have bug.
3. commands are easier to handle when have fixed length.

==============================================================
Source Code:

LED- VB (visual basic) program and command files:
https://dl.dropbox.com/u/457167/Blog_Download_Resources/PC_Arduino_Controller_VB.7z

Hexapd – VB (visual basic) program and command files:
https://dl.dropbox.com/u/457167/Blog_Download_Resources/Hexapod_Controller_VB.7z

Arduino Main program (An example on hexapod robot, to just make you understand):

1 // Oscar's Project
2 #include <Servo.h>
3 #include "serial_command.h"
4
5 // ========== Position Table ===========
6 SerialCommand command;
7
8 // ========= Servo ===================
9 // 12 servos
10 // first 6 - legs    last 6 - sholders
11 Servo servo[12];
12 int servoPos[12];
13
14 // ========== Pins ============
15 // first 6 legs, last 6 sholder
16 const byte pin[12] = {8,9,10,11,12,13,2,3,4,5,6,7};
17
18 void setup()
19 {
20     Serial.begin(9600);
21
22     // == Setup Servos ==
23
24     for (int i=0; i<12; i++){
25         servo[i].attach(pin[i]);
26         servoPos[i] = 1400;
27         servo[i].writeMicroseconds(servoPos[i]);
28         delay(100);
29     }
30
31     delay(2000);
32
33     command.Reset();
34 }
35
36 void loop()
37 {
38     if (command.ReceiveCommand()){
39         if (command.DecodeCommand()){
40             if (command.ExecuteCommand()) {
41                 for(int curPos=0; curPos<command.loops; curPos++){
42                     for (int i=0; i<12; i++){
43
44                         // UPDATE POSITIONS
45                         servoPos[i] += command.servoPosAdjust[i];
46                         servoPos[i] = constrain(servoPos[i], 600, 2400);
47
48                         // WRITE POSITIONS
49                         servo[i].writeMicroseconds(servoPos[i]);
50                     }
51                     delay(40);
52                 }
53
54                 // Finish, send signal to PC
55                 Serial.write('1');
56             }
57             else
58                 Serial.println("execution failed"); // execution failed
59         }
60         else
61             Serial.println("decoding failed"); // decoding failed
62
63         //if (command.executed && command.listening)
64         command.Reset();
65     }
66 }

Command class (this is the class for the command system, it’s a general purpose class)

1 #include "WProgram.h"
2
3 class SerialCommand{
4
5 private:
6
7     static const int MAX_SERVO_NUM = 18;
8     static const int SINGLE_COMMAND_LENGTH = 3+5;
9     static const int MAX_COMMAND_LENGTH = MAX_SERVO_NUM * SINGLE_COMMAND_LENGTH + 5;
10
11     int index;
12     int command[MAX_COMMAND_LENGTH]; // longest command is 12 char long
13
14 public:
15
16     boolean executed; // true - ready for new command
17     boolean listening; // true - recieved part of the command but not '/' yet
18     // false - still listening to command
19     int pin;    // pin number, OR servo number
20     int mode;   // 0 - write, 1 - read, 2 - servo control
21     int data;
22
23     // Servo data
24
25     int loops;
26     int servoPos[MAX_SERVO_NUM];
27     int servoPos_LastUpdated;
28     int servoPosChange[MAX_SERVO_NUM];
29     float servoPosAdjust[MAX_SERVO_NUM];
30
31     // ============ Functions ===============
32
33 private:
34     long GetSerialByte();
35     int Char2Int(char chr);
36
37 public:
38     SerialCommand();
39     void Reset();
40     boolean ReceiveCommand();
41     boolean DecodeCommand();
42     boolean ExecuteCommand();
43
44 };

(this is the command class functions, goes with the class)

1 #include "serial_command.h"
2
3 SerialCommand::SerialCommand(){
4
5     servoPos_LastUpdated = 1500;
6     for (int i=0; i<MAX_SERVO_NUM; i++)
7         servoPos[i] = 1500; // longest command is 12 char long
8
9     Reset();
10
11 }
12
13 long SerialCommand::GetSerialByte(){
14
15     return Serial.read();
16
17 }
18
19 int SerialCommand::Char2Int(char chr) {
20     if ((chr < '0') || (chr > '9'))
21         return -1;
22     else
23         return chr - '0';
24 }
25
26 // =========================================================
27 // ===================== Main functions ====================
28 // =========================================================
29
30 boolean SerialCommand::ReceiveCommand(){
31
32     if (Serial.available() > 0) {
33
34         // determine
35         if (index >= MAX_COMMAND_LENGTH)    return false;
36
37         // Receiving
38         command[index] = GetSerialByte();
39         listening = false;
40         if (command[index] == '/')
41             return true;
42         listening = true;
43         index++;
44
45     }
46
47     // no signal available
48     return false;
49
50 }
51
52 boolean SerialCommand::DecodeCommand(){
53
54     if (command[index] != '/')     return false;
55
56     boolean negative = false;
57     int indexCur = 0;
58
59     // Decoding
60
61     // differentiate type of command
62     if (command[indexCur] == 'M') {
63         // pin mode
64         // ... more code...
65     }
66     else if (command[indexCur] == 'S'){
67
68         // servo mode
69         while (indexCur < index) {
70             int tempServoNum = 0;
71             int tempServoPos = 0;
72
73             // extracting servo number (2 integers)
74             for(int i=0; i<2; i++){
75                 indexCur++;
76                 int temp = Char2Int(command[indexCur]);
77                 if (temp < 0)           return false;
78                 tempServoNum = tempServoNum*10 + temp;
79             }
80
81             // extracting pos number
82             indexCur++;
83
84             if (command[indexCur] != 'C')             return false;
85
86             indexCur++;
87             boolean negative = Char2Int(command[indexCur]);
88             for (int i=0; i<4; i++) {
89                 indexCur++;
90                 int temp = Char2Int(command[indexCur]);
91                 if (temp < 0)           return false;
92                 tempServoPos = tempServoPos*10 + temp;
93             }
94             if (negative) tempServoPos = -tempServoPos;
95             servoPosChange[tempServoNum] = tempServoPos;
96
97             // extracting loop number
98             indexCur++;
99             if (command[indexCur] == 'L'){
100
101                 loops = 0;
102                 for (int i=0; i<4; i++){
103                     indexCur++;
104                     int temp = Char2Int(command[indexCur]);
105                     if (temp < 0)           return false;
106                     loops = loops*10 + temp;
107                 }
108
109                 for (int i=0; i<MAX_SERVO_NUM; i++)
110                     servoPosAdjust[i] = (float)servoPosChange[i]/(float)loops;
111
112                 indexCur++;
113
114             }
115         // end of while indexCur < index
116
117         return true;
118     // end of if 'S'
119
120     else {
121         ;// unknown command
122         // ... more code...
123     }
124 }
125
126 boolean SerialCommand::ExecuteCommand(){
127     /*
128     if ((pin < 0) || (mode < 0) || (data < 0))
129     return false;
130     */
131     switch (mode){
132     case 0:
133         // do noting.
134         break;
135     case 1:
136         // ... more code...
137         digitalWrite(pin,data);
138         break;
139
140     case 2:
141         // ... more code...
142         digitalRead(pin);
143         break;
144
145     case 3:
146         // ... more code...
147         servoPos[pin] = data;
148         servoPos_LastUpdated = data;
149         break;
150     }
151
152     executed = true;
153     return true;
154 }
155
156 void SerialCommand::Reset(){
157
158     // initialize variables and parameters
159     executed = false;
160     listening = false;
161
162     index = 0;
163     //loops = 0;
164     mode = 0;
165     pin = 0;
166     data = 0;
167
168     for (int i=0; i<MAX_COMMAND_LENGTH; i++){
169         command[i] = 0;
170     }
171
172     for (int i=0; i<MAX_SERVO_NUM; i++){
173         servoPosChange[i] = 0;
174         servoPosAdjust[i] = 0;
175     }
176
177 }

This is also useful when we use bluetooth to control arduino.

And, How?

Arduino has already provided a serial communication class, and there are built in examples of how to use them. Here is the official doc:

http://arduino.cc/en/Reference/Serial

I will first try to establish a basic class and working Arduino program in the Arduino development IDE, and then move on to write a VB program to provide better and more user friendly interface. I will also publish my source code in the near future.

After all, you will can do things like these:

Wii Nunchuck Arduino Tutorial

wiichuck_adapter1

Why Wii Nunchuck Arduino?

You can create and build endless electronics design and project with the powerful Arduino, for example a robot. By attaching Wii Nunchuck Arduino, you create the opportunity to control Arduino using the way we most familiar with, the way we play games! Not to mention, Wii Nunchuck is cheap (~5 US dollars), and it also has three-axis accelerometer for motion sensing, which is very useful.

What hardware are required?

  • Arduino
  • Wii Nunchuck
  • Nunchuck – Arduino Adapter

wiichuck_adapter2

wiichuck_adapter3

Wii Nunchuck Arduino Hardware Explained

Wiimote Bus Pins (6-pin proprietary connector on Wiimote)

The wii nunchuck accessory bus is a 6 pin data connector. However, only 4 pins are useful to us.

Looking into Wiimote:

|   135   |
|   246   |
|___---___|
  • 1 (Red wire) – +3V
  • 2 (Yellow wire) – Clk
  • 3 (Red wire) – Attachment detection?
  • 4 (No wire) – Unknown (unconnected at Nunchuk connector)
  • 5 (Green wire) – Data
  • 6 (White wire) – GND

Hook up Arduino Uno and Wii Nunchuck

wiichuck-diag

wiichuck_adapter1

Hook up Arduino Mega and Wii Nunchuck

  • + to +3.3V
  • – to GND
  • d to SDA (pin 20)
  • c to SCL (pin 21)

wii-nunchuk-arduino-mega

That’s the hardware part, let’s have a look at the software side (library)

If you want to discuss or share your ideas, you can post something in our forum here.

Wii Nunchuck Arduino Library

I have attached the library we need, and explain the the functions we use, and how to use these functions. This is a modified version of the original source code from Here

How to use them?

you need to include these libraries:

    #ifndef NUNCHUCK_H
        #define NUNCHUK_H
        #include <Wire.h>
        #include "nunchuck.h"
    #endif

Then initialize nunchuck in the Void setup() function

Serial.begin (19200); // Required by Wii Nunchuck
NunC_Init(0); // initialize nunchuck

In Loop() function, you check whether there is a new command, after the if loop, you send a signal back the Wii Nunchuck to tell it you are ready for next input, and add a little delay to allow transmissions to happen:

if (NunC_RecieveCommand() == true)
{
    // Get the input values, and do your stuff here
}
NunC_SendNextByteRequest(); // send the request for next bytes
delay(10);

To get the inputs, you can use these global variables

// NunC_JX - 0 to 255
// NunC_JY - 0 to 255
// NunC_AX - 0 to 255
// NunC_AY - 0 to 255
// NunC_AZ - 0 to 255
// NunC_BC - 0, 1
// NunC_BZ - 0, 1

For example, if I want to get the accelerometer X-axis value, I do this

X = map(NunC_AX, 0, 255, -13, 13);

I map it to a range that is useful to the application.

Here is the Library source code:


#define POWER_VIA_PORT_C2_C3 1

#define USE_NEW_WAY_INIT 1 
#define WII_IDENT_LEN ((byte)6)
#define WII_TELEGRAM_LEN ((byte)6)
#define WII_NUNCHUCK_TWI_ADR ((byte)0x52)

#include "WProgram.h"
#include <string.h> 
#include <utility\twi.h>
#undef int
#include <stdio.h>

static uint8_t outbuf[WII_TELEGRAM_LEN];	 // array to store arduino output
int cnt = 0;

// -------- output -------
byte NunC_JX = 0;
byte NunC_JY = 0;
byte NunC_AX = 0;
byte NunC_AY = 0;
byte NunC_AZ = 0;
boolean NunC_BC = 0;
boolean NunC_BZ = 0;

// ===========================================================
// ================  Private Functions  ======================
// ==========================================================

byte readControllerIdent(byte* pIdent)
{
	byte rc = 1;

	// read identification
	Wire.beginTransmission (WII_NUNCHUCK_TWI_ADR);	// transmit to device 0x52
	Wire.send (0xFA);	 // sends memory address of ident in controller
	if(Wire.endTransmission () == 0)	// stop transmitting
	{
		byte i;
		Wire.requestFrom (WII_NUNCHUCK_TWI_ADR, WII_TELEGRAM_LEN);	// request data from nunchuck
		for (i = 0; (i < WII_TELEGRAM_LEN) && Wire.available (); i++) 		{ 			pIdent[i] = Wire.receive();	// receive byte as an integer 		} 		if(i == WII_TELEGRAM_LEN) 		{ 			rc = 0; 		} 	} 	return rc; } void clearTwiInputBuffer(void) { 	// clear the receive buffer from any partial data 	while( Wire.available ()) 		Wire.receive (); } // Decode data format that original Nunchuck uses with old init sequence. This never worked with // other controllers (e.g. wireless Nunchuck from other vendors) char nunchuk_decode_byte (char x) { #ifndef USE_NEW_WAY_INIT 	x = (x ^ 0x17) + 0x17; #endif 	return x; } void ConvertOutputs(){      /*   Joy - X 0 137 255      [0]         Y 0 142 255      [1]   Acc - X 290  560  715  [2]  (*2*2)         Y 320  535  750  [3]  (*2*2)   */   // will use Joy X, Y for Coxa and femur, Acc Y for Tibia   /*   PosX = outbuf[1]/4;   PosZ = (outbuf[0]-128)/2;   PosY = (outbuf[2] - 72)/2;   */      NunC_JX = outbuf[0];   NunC_JY = outbuf[1];   NunC_AX = map(outbuf[2]*2*2, 256, 768, 0, 255);   NunC_AY = map(outbuf[3]*2*2, 256, 768, 0, 255);   NunC_AZ = map(outbuf[4]*2*2, 256, 768, 0, 255);   if ((outbuf[5] >> 0) & 1)  NunC_BZ = 0;
  else                       NunC_BZ = 1;
  if ((outbuf[5] >> 1) & 1)  NunC_BC = 0;
  else                       NunC_BC = 1;

  // buffer 5 also contains the least significant bit of accelerometer data
  if ((outbuf[5] >> 2) & 1)  NunC_AX += 2;
  if ((outbuf[5] >> 3) & 1)  NunC_AX += 1;
  if ((outbuf[5] >> 4) & 1)  NunC_AY += 2;
  if ((outbuf[5] >> 5) & 1)  NunC_AY += 1;
  if ((outbuf[5] >> 6) & 1)  NunC_AZ += 2;
  if ((outbuf[5] >> 7) & 1)  NunC_AZ += 1;

}

// ===========================================================
// ================  Public Functions  ======================
// ==========================================================

// params:
// timeout: abort when timeout (in ms) expires, 0 for unlimited timeout
// return: 0 == ok, 1 == timeout
void NunC_Init (unsigned short timeout)
{

  // ----------------------- setup power pins -----------------------

    #ifdef POWER_VIA_PORT_C2_C3 // power supply of the Nunchuck via port C2 and C3
	PORTC &=~ _BV(PORTC2);
	PORTC |= _BV(PORTC3);
	DDRC |= _BV(PORTC2) | _BV(PORTC3); // make outputs
	delay(100); // wait for things to stabilize
    #endif

  // ----------------------- timer speed? -----------------------
	Wire.begin(); // initialize i2c
	// we need to switch the TWI speed, because the nunchuck uses Fast-TWI
	// normally set in hardware\libraries\Wire\utility\twi.c twi_init()
	// this is the way of doing it without modifying the original files
    #define TWI_FREQ_NUNCHUCK 400000L
	TWBR = ((CPU_FREQ / TWI_FREQ_NUNCHUCK) - 16) / 2;

	byte rc = 1;

  // ----------------------- initialize nunchuck -----------------------
    #ifndef USE_NEW_WAY_INIT
	// look at <http://wiibrew.org/wiki/Wiimote#The_Old_Way> at "The Old Way"
	Wire.beginTransmission (WII_NUNCHUCK_TWI_ADR);	// transmit to device 0x52
	Wire.send (0x40);	 // sends memory address
	Wire.send (0x00);	 // sends sent a zero.
	Wire.endTransmission ();	// stop transmitting
    #else
	// disable encryption
	// look at <http://wiibrew.org/wiki/Wiimote#The_New_Way> at "The New Way"

	unsigned long time = millis();
	do
	{
		Wire.beginTransmission (WII_NUNCHUCK_TWI_ADR);	// transmit to device 0x52
		Wire.send (0xF0);	 // sends memory address
		Wire.send (0x55);	 // sends data.
		if(Wire.endTransmission() == 0) // stop transmitting
		{
			Wire.beginTransmission (WII_NUNCHUCK_TWI_ADR);	// transmit to device 0x52
			Wire.send (0xFB);	 // sends memory address
			Wire.send (0x00);	 // sends sent a zero.
			if(Wire.endTransmission () == 0)	// stop transmitting
			{
				rc = 0;
			}
		}
	}
	while (rc != 0 && (!timeout || ((millis() - time) < timeout)));
      #endif

  // ----------------------- finish setup -----------------------
	// display the identification bytes, must be "00 00 A4 20 00 00" for the Nunchuck
	byte i;
	if(readControllerIdent(outbuf) == 0)
	{
		Serial.print("Ident=");
		for (i = 0; i < WII_TELEGRAM_LEN; i++)
		{
			Serial.print(outbuf[i], HEX);
			Serial.print(' ');
		}
		Serial.println();
	}

	Serial.println("Finished setup");

}

boolean NunC_RecieveCommand(){
	Wire.requestFrom (WII_NUNCHUCK_TWI_ADR, WII_TELEGRAM_LEN);	// request data from nunchuck

	for (cnt = 0; (cnt < WII_TELEGRAM_LEN) && Wire.available (); cnt++) 		outbuf[cnt] = nunchuk_decode_byte (Wire.receive ());	// receive byte as an integer 	clearTwiInputBuffer(); 	// If we recieved the 6 bytes, then go print them 	if (cnt >= WII_TELEGRAM_LEN){
          ConvertOutputs();
          return true;
        }
        else                          
          return false;
}

void NunC_SendNextByteRequest()
{
	// I don't know why, but it only works correct when doing this exactly 3 times
	// otherwise only each 3rd call reads data from the controller (cnt will be 0 the other times)
	for(byte i = 0; i < 3; i++)
	{
		Wire.beginTransmission (WII_NUNCHUCK_TWI_ADR);	// transmit to device 0x52
		Wire.send (0x00);	 // sends one byte
		Wire.endTransmission ();	// stop transmitting
	}
}

void print ()
{

     Serial.print (NunC_JX, DEC);
     Serial.print ("\t");

     Serial.print (NunC_JY, DEC);
     Serial.print ("\t");

     Serial.print (NunC_AX, DEC);
     Serial.print ("\t");

     Serial.print (NunC_AY, DEC);
     Serial.print ("\t");

     Serial.print (NunC_AZ, DEC);
     Serial.print ("\t");

     Serial.print (NunC_BZ, DEC);
     Serial.print ("\t");

     Serial.print (NunC_BC, DEC);
     Serial.print ("\t");

     Serial.print ("\r\n");
}

Testing Wii Nunchuck with Arduino

To test the Wii Nunchuck and making sure it’s working properly, we can verify it’s input in the Arduino Serial Monitor. In the Serial Monitor you should be getting data like this.

testing-arduino-with-wii-nunchuck-remote-baud rate

1 #ifndef NUNCHUCK_H
2   #define NUNCHUK_H
3   #include <Wire.h>
4   #include "nunchuck.h"
5 #endif
6
7 void setup(){
8
9     Serial.begin (19200); // Required by Wii Nunchuck
10     NunC_Init(0); // initialize nunchuck
11
12 }
13
14 void loop(){
15
16     if (NunC_RecieveCommand() == true){
17
18         NunC_print ();
19
20     }
21     NunC_SendNextByteRequest(); // send the request for next bytes
22     delay(10);
23
24 }

Connect Raspberry Pi and Arduino with Serial USB Cable

Posted on May 20, 2013 by 

raspberry-pi-to-arduino-via-usb-cable

Using USB Cable Between Raspberry Pi and Arduino

There are many ways of connecting the Raspberry Pi and Arduino, such as using the GPIO and Serial pins and using I2C. But this could be one of the easiest way to get them talking, because hardware that required is minimal: all you will need is a micro USB cable that comes with the Arduino. To Setup your Raspberry Pi, check out this article.

To Demonstrate how this works, I will be doing two little projects, one for data going to Raspberry Pi from Arduino, the other one for the opposite. First of all, make sure you have installed pySerial, which gives you the ability to read from and write to the serial port with Python Programming language. People have used it before with Arduino, so it’s been proven to be working, you can check this out.

Arduino Talking to Raspberry Pi via USB cable

We will send ‘Hi’ from the Arduino to the Raspberry Pi every 2 seconds. Here is the Arduino source code.

1 void setup(){
2   Serial.begin(9600);
3 }
4
5 void loop(){
6   Serial.println("Hello Pi");
7   delay(2000);
8 }

Run Python 2 on Raspberry Pi. You will find this from the menu under Programming, you should use Python 2 not 3.

Type the following after >>>

import serial
ser = serial.Serial('/dev/ttyACM0', 9600)

The first argument – /dev/ttyACM0 is the name for the USB interface used. To find out the port name, we need to run this command in terminal without Arduino plugged in:

ls /dev/tty*

Now plug in your Arduio and run the command again. If a new name appears, then this is the name of your port.

The second argument – 9600 is the baud rate and should match with what you set in the Arduino program.

Now lets start a loop listening for messages from the Arduino.

while 1 :
    ser.readline()

You will need two hit enter twice after you type the second line. Messages ‘Hi’ should now start to appear every 2 seconds. You can press Ctrl + C to stop (interrupt) the Python program.

Raspberry Pi Sending Data To Arduino

In this example, Raspberry Pi will be sending back a single number, and the Arduino will turn on and off the LED on Pin 12 so many times.

1 const int ledPin = 12;
2
3 void setup(){
4   pinMode(ledPin, OUTPUT);
5   Serial.begin(9600);
6 }
7
8 void loop(){
9   if (Serial.available())  {
10      light(Serial.read() - '0');
11   }
12   delay(500);
13 }
14
15 void light(int n){
16   for (int i = 0; i < n; i++)  {
17     digitalWrite(ledPin, HIGH);
18     delay(100);
19     digitalWrite(ledPin, LOW);
20     delay(100);
21   }
22 }

On the Raspberry Pi Side, you need to type

ser.write('3')

Now you should see the LED on the Arduino light up 3 times.

raspberry-pi-and-arduino-connected-usb-cable

There you go, be creative and you will find there are so many things you can do. For example we could control some motor or LCD on the Arduino from the Raspberry Pi.

Using switch to control Piezo speaker

Posted on November 19, 2011 by 

piezo__buzzer__

In this project, we will learn how to use a speaker (peizo sounder) and use switch button to change the pitch of the sound.

Sorry about this one, you might find it a bit difficult to digest at first, and I didn’t realise it’s actually harder than it sounds. Anyway, spend some time on the code, let me know if you have problem understanding the code, or you have a better solution.

In this project, we will be using a low power speaker called Peizo speaker (around 8 ohm) that look like this:
This program basically changes states as the button is pressed, between OFF, TONE1 and TONE2. This is the circuit diagram:
One thing we need to aware of in this project before we do any programming, is that, we will need to create a header file to store all the pitches as sensible names that we can use directly. Let’s create a new tap in the Arduino programming software:
And name it as “pitches.h”. Copy and save the following:
#define NOTE_B0  31
#define NOTE_C1  33
#define NOTE_CS1 35
#define NOTE_D1  37
#define NOTE_DS1 39
#define NOTE_E1  41
#define NOTE_F1  44
#define NOTE_FS1 46
#define NOTE_G1  49
#define NOTE_GS1 52
#define NOTE_A1  55
#define NOTE_AS1 58
#define NOTE_B1  62
#define NOTE_C2  65
#define NOTE_CS2 69
#define NOTE_D2  73
#define NOTE_DS2 78
#define NOTE_E2  82
#define NOTE_F2  87
#define NOTE_FS2 93
#define NOTE_G2  98
#define NOTE_GS2 104
#define NOTE_A2  110
#define NOTE_AS2 117
#define NOTE_B2  123
#define NOTE_C3  131
#define NOTE_CS3 139
#define NOTE_D3  147
#define NOTE_DS3 156
#define NOTE_E3  165
#define NOTE_F3  175
#define NOTE_FS3 185
#define NOTE_G3  196
#define NOTE_GS3 208
#define NOTE_A3  220
#define NOTE_AS3 233
#define NOTE_B3  247
#define NOTE_C4  262
#define NOTE_CS4 277
#define NOTE_D4  294
#define NOTE_DS4 311
#define NOTE_E4  330
#define NOTE_F4  349
#define NOTE_FS4 370
#define NOTE_G4  392
#define NOTE_GS4 415
#define NOTE_A4  440
#define NOTE_AS4 466
#define NOTE_B4  494
#define NOTE_C5  523
#define NOTE_CS5 554
#define NOTE_D5  587
#define NOTE_DS5 622
#define NOTE_E5  659
#define NOTE_F5  698
#define NOTE_FS5 740
#define NOTE_G5  784
#define NOTE_GS5 831
#define NOTE_A5  880
#define NOTE_AS5 932
#define NOTE_B5  988
#define NOTE_C6  1047
#define NOTE_CS6 1109
#define NOTE_D6  1175
#define NOTE_DS6 1245
#define NOTE_E6  1319
#define NOTE_F6  1397
#define NOTE_FS6 1480
#define NOTE_G6  1568
#define NOTE_GS6 1661
#define NOTE_A6  1760
#define NOTE_AS6 1865
#define NOTE_B6  1976
#define NOTE_C7  2093
#define NOTE_CS7 2217
#define NOTE_D7  2349
#define NOTE_DS7 2489
#define NOTE_E7  2637
#define NOTE_F7  2794
#define NOTE_FS7 2960
#define NOTE_G7  3136
#define NOTE_GS7 3322
#define NOTE_A7  3520
#define NOTE_AS7 3729
#define NOTE_B7  3951
#define NOTE_C8  4186
#define NOTE_CS8 4435
#define NOTE_D8  4699
#define NOTE_DS8 4978
Here is the code, notice we have to include the line “#include “pitches.h” to use our pitches names.
1 /*
2 play sounds on a Piezo speaker. oscar's project
3 Every time button is pressed, it moves to the next state. The states are:
4 Off - On(Note-C2) - On(Note-D3) - Off - ...
5 */
6
7 #include "pitches.h"
8
9 int buttonPin = 1;  // button input pin
10 int speakerPin = 2;  // speaker output pin
11
12 int buttonState = 0;
13 int beingPressed = 0;
14 int state = 0; // 0, 1, 2
15
16 // notes to play
17 int notes[] = {
18     NOTE_C2,
19     NOTE_D3
20 };
21
22 void setup() {
23
24     // initialize the LED pin as an output:
25     pinMode(buttonPin, INPUT);
26
27 }
28
29 void loop() {
30
31     // read the state of the pushbutton value:
32     buttonState = digitalRead(buttonPin);
33
34     if (buttonState == HIGH){
35         // this is only true for once after button is pressed
36         if (beingPressed == LOW){
37             if (state >= 2) state = 0;
38             else state++;
39         }
40         // this is the rising edge of the button signal
41         beingPressed = HIGH;
42     }
43     else {
44         // falling edge of the button signal
45         if (beingPressed == HIGH)
46             beingPressed = LOW;
47     }
48
49     if (state == 1)
50         tone(speakerPin, notes[0], 10); // param.:(output pin, pitch, duration)
51     else if (state == 2)
52         tone(speakerPin, notes[1], 10);
53     else
54         ;// DO NOTHING
55
56     // give delay to let controller finish 'tone' instruction (same duration as 'tone')
57     delay(10);
58 }

Use switch and potentiometer to control a LED

Posted on November 19, 2011 by 

potentiometer

In our first project, I will be showing you the basic connections of a LED circuit.
To make it more interesting and challenging, I later on replace the switch with a potentiometer, to control the brightness.
================================
Using 4 legs Switch
================================
potentiometer
1 /*
2   Oscar's project
3
4   turn LED on and off with a switch
5
6 */
7
8 // constants type won't change (just good practice, can declare without)
9 // set pin numbers:
10 const int buttonPin = 1;     // the number of the pushbutton pin
11 const int ledPin =  2;      // the number of the LED pin
12
13 // variables will change:
14 int buttonState = 0;         // variable for reading the pushbutton status
15
16 void setup() {
17
18     // initialize the LED pin as an output:
19     pinMode(ledPin, OUTPUT);
20     // initialize the pushbutton pin as an input:
21     pinMode(buttonPin, INPUT);
22 }
23
24 void loop() {
25
26     // read the state of the pushbutton value:
27     buttonState = digitalRead(buttonPin);
28
29     // check if the pushbutton is pressed.
30     // if it is, the buttonState is HIGH:
31     if (buttonState == HIGH)
32         // turn LED on:
33         digitalWrite(ledPin, HIGH);
34     else
35         // turn LED off:
36         digitalWrite(ledPin, LOW);
37
38     // have some delay (optional)
39     delay(30);
40 }
================================
Using Potentiometer
================================When you are connecting to different Digital outputs, you will find some doesn’t give you the change of brightness effect, but a switching on/off effect, such as 2. Port 3 is the first PWM output in order, so we will use that.The reason is because we need to have PWM (pulse-width modulation) output to have an analogue-like effect, otherwise we will only have a pure digital output which is only on and off. Read more about PWM here XXX.
 
1 /*
2 Oscar's project
3 adjust LED lightness using potential meter
4
5 */
6
7 int brightness = 0;    // how bright the LED is
8 int ledPin = 3; // PWM output
9
10 void setup() {
11     // declare pin 9 to be an output:
12     pinMode(ledPin, OUTPUT);
13 }
14
15 void loop() {
16     int sensorValue = analogRead(A0);
17
18     // sensorValue 0 - 1023
19     // brightness 0 - 255
20     brightness = sensorValue/4;
21
22     // set the brightness of pin 9:
23     analogWrite(ledPin, brightness);
24
25     // wait for 30 milliseconds to see the dimming effect
26     delay(30);
27 }

How to control a Servo

Posted on November 28, 2011 by 

servo

In this one, servo is programmed to be controlled by two buttons, one turns servo to the left and the other one turns it to the right. When the servo is turning, corresponding LED will be switched on to indicate the operation.
Because Arduino has built-in library for controlling servo, which makes servo a really easy kit to use. In this project, I will be using a servo to turn the IR sensor around constantly.
This is the circuit Diagram:
This is the code:
// Oscar’s Project
//
// There are 2 input buttons (turn left and right), when button is pressed, the servo turns and corresponding LED is lit up.

#include

Servo myservo;  // create servo object to control a servo
// a maximum of eight servo objects can be created

int pos = 90;    // variable to store the servo position
const int maxDeg = 160;
const int minDeg = 5;

const int leftPin = 3;
const int rightPin = 2;

const int led1Pin = 6; // indicator
const int led2Pin = 5; // indicator

const int outputPin = 9; // pwm function will be disabled on pin 9 and 10 if using servo

int leftPressed = 0;
int rightPressed = 0;

void setup()
{
myservo.attach(outputPin);  // attaches the servo on pin 9 to the servo object
pinMode(leftPin, INPUT);
pinMode(rightPin, INPUT);
pinMode(led1Pin, OUTPUT);
pinMode(led2Pin, OUTPUT);
}

void loop()
{
leftPressed = digitalRead(leftPin);
rightPressed = digitalRead(rightPin);

if(leftPressed){
if(pos < maxDeg) pos += 3;
myservo.write(pos);              // tell servo to go to position in variable ‘pos’
digitalWrite(led1Pin,HIGH);
}
else
digitalWrite(led1Pin,LOW);

if(rightPressed){
if(pos > minDeg) pos -= 3;
myservo.write(pos);              // tell servo to go to position in variable ‘pos’
digitalWrite(led2Pin,HIGH);
}
else
digitalWrite(led2Pin,LOW);

delay(15);                       // waits 15ms for the servo to reach the position

}

Learn how to use 4-digit-7-segment LED Display

Posted on November 23, 2011 by 

4digit-7segment-display-white

In our last project, I shown you how to use one digit 7 segment LED display. In this one, I will show you how to use all 4 digits. I will be using the class i created in our last tutorial.

As you might notice, all four digits are controlled by the same LED inputs (a, b, c… ,f, g), how are we going to display different number on each digit? Actually, we can disable the previous digit before we display the next one. If we do this quick enough, human eyes will not be able to tell the difference.

Result:

Let’s connect “1Y” to one of the digital output instead of ground, so we can  disconnect the circuit to disable LEDs if we want by raising voltage. For example, to display ’1′ on first digit, we then disable it and display ’2′ on the second digit, we can make the digital output connected to “1Y” “HIGH”, display ’2′, and make digital output connected to “2Y” LOW.
I have updated the class to support displaying multiple digit numbers up to 9999. for example you can display the number ’1234 easily by the 2 lines:
LEDDisplay disp;
disp.DisplayNumber(1234);
Easy! See my source code for how to implement.
Here is the Circuit Diamgram: (see blue lines for changes from the last one )
Source Code for the class:
1 #include "WProgram.h"  //standard types and constants of the Arduino language
2
3 enum Num { NOTHING = -1, ZERO = 0, ONE = 1, TWO = 2, THREE = 3, FOUR = 4, FIVE = 5,
4 SIX = 6, SEVEN = 7, EIGHT = 8, NINE = 9, DECIMAL_POINT = 10}; // 10 means decimal point, -1 means nothing is being displayed
5
6 class LEDDisplay {
7
8     public:
9     Num displaying;   // indicate which number is being displayed
10
11     private:
12     int aPin;  // these are the output pins
13     int bPin;
14     int cPin;
15     int dPin;
16     int ePin;
17     int fPin;
18     int gPin;
19     int dpPin;
20
21     int y1Pin;  // these are used to control display which digit
22     int y2Pin;
23     int y3Pin;
24     int y4Pin;
25
26     public:
27     LEDDisplay();  // constructor with default output pins
28     LEDDisplay(int a, int b, int c, int d, int e, int f, int g, int dp, inty1, int y2, int y3, int y4);  // constructor with specified output pins
29     void DisplayDigit (Num digit);
30     void DisplayNumber (int number);
31
32 };
1 #include "Seven_Seg_LED_Display.h"
2
3 LEDDisplay::LEDDisplay () {
4
5     displaying = NOTHING;
6
7     for (int outputPin = 1; outputPin <= 8; outputPin++)
8         pinMode(outputPin, OUTPUT);
9
10     // LED pin
11     aPin = 1;
12     bPin = 2;
13     cPin = 3;
14     dPin = 4;
15     ePin = 5;
16     fPin = 6;
17     gPin = 7;
18     dpPin = 8;
19
20     for (int yPin = 10; yPin <= 13; yPin++)
21         pinMode(yPin, OUTPUT);
22
23     // control to display which digit
24     y1Pin = 10;
25     y2Pin = 11;
26     y3Pin = 12;
27     y4Pin = 13;
28
29 }
30
31 LEDDisplay::LEDDisplay(int a, int b, int c, int d, int e, int f, int g, intdp, int y1, int y2, int y3, int y4) {
32
33     displaying = NOTHING;
34
35     pinMode(aPin = a, OUTPUT);
36     pinMode(bPin = b, OUTPUT);
37     pinMode(cPin = c, OUTPUT);
38     pinMode(dPin = d, OUTPUT);
39     pinMode(ePin = e, OUTPUT);
40     pinMode(fPin= f, OUTPUT);
41     pinMode(gPin = g, OUTPUT);
42     pinMode(dpPin = dp, OUTPUT);
43     pinMode(y1Pin = y1, OUTPUT);
44     pinMode(y2Pin = y2, OUTPUT);
45     pinMode(y3Pin = y3, OUTPUT);
46     pinMode(y4Pin = y4, OUTPUT);
47
48 }
49
50 void LEDDisplay::DisplayDigit (Num digit){
51
52     displaying = digit;
53
54     switch (digit) {
55         case ZERO:
56             digitalWrite(aPin, HIGH);
57             digitalWrite(bPin, HIGH);
58             digitalWrite(cPin, HIGH);
59             digitalWrite(dPin, HIGH);
60             digitalWrite(ePin, HIGH);
61             digitalWrite(fPin, HIGH);
62             digitalWrite(gPin, LOW);
63             digitalWrite(dpPin, LOW);
64         break;
65
66         case ONE:
67             digitalWrite(aPin, LOW);
68             digitalWrite(bPin, HIGH);
69             digitalWrite(cPin, HIGH);
70             digitalWrite(dPin, LOW);
71             digitalWrite(ePin, LOW);
72             digitalWrite(fPin, LOW);
73             digitalWrite(gPin, LOW);
74             digitalWrite(dpPin, LOW);
75             break;
76         case TWO:
77             digitalWrite(aPin, HIGH);
78             digitalWrite(bPin, HIGH);
79             digitalWrite(cPin, LOW);
80             digitalWrite(dPin, HIGH);
81             digitalWrite(ePin, HIGH);
82             digitalWrite(fPin, LOW);
83             digitalWrite(gPin, HIGH);
84             digitalWrite(dpPin, LOW);
85             break;
86         case THREE:
87             digitalWrite(aPin, HIGH);
88             digitalWrite(bPin, HIGH);
89             digitalWrite(cPin, HIGH);
90             digitalWrite(dPin, HIGH);
91             digitalWrite(ePin, LOW);
92             digitalWrite(fPin, LOW);
93             digitalWrite(gPin, HIGH);
94             digitalWrite(dpPin, LOW);
95             break;
96         case FOUR:
97             digitalWrite(aPin, LOW);
98             digitalWrite(bPin, HIGH);
99             digitalWrite(cPin, HIGH);
100             digitalWrite(dPin, LOW);
101             digitalWrite(ePin, LOW);
102             digitalWrite(fPin, HIGH);
103             digitalWrite(gPin, HIGH);
104             digitalWrite(dpPin, LOW);
105             break;
106         case FIVE:
107             digitalWrite(aPin, HIGH);
108             digitalWrite(bPin, LOW);
109             digitalWrite(cPin, HIGH);
110             digitalWrite(dPin, HIGH);
111             digitalWrite(ePin, LOW);
112             digitalWrite(fPin, HIGH);
113             digitalWrite(gPin, HIGH);
114             digitalWrite(dpPin, LOW);
115             break;
116         case SIX:
117             digitalWrite(aPin, HIGH);
118             digitalWrite(bPin, LOW);
119             digitalWrite(cPin, HIGH);
120             digitalWrite(dPin, HIGH);
121             digitalWrite(ePin, HIGH);
122             digitalWrite(fPin, HIGH);
123             digitalWrite(gPin, HIGH);
124             digitalWrite(dpPin, LOW);
125             break;
126         case SEVEN:
127             digitalWrite(aPin, HIGH);
128             digitalWrite(bPin, HIGH);
129             digitalWrite(cPin, HIGH);
130             digitalWrite(dPin, LOW);
131             digitalWrite(ePin, LOW);
132             digitalWrite(fPin, LOW);
133             digitalWrite(gPin, LOW);
134             digitalWrite(dpPin, LOW);
135             break;
136         case EIGHT:
137             digitalWrite(aPin, HIGH);
138             digitalWrite(bPin, HIGH);
139             digitalWrite(cPin, HIGH);
140             digitalWrite(dPin, HIGH);
141             digitalWrite(ePin, HIGH);
142             digitalWrite(fPin, HIGH);
143             digitalWrite(gPin, HIGH);
144             digitalWrite(dpPin, LOW);
145             break;
146         case NINE:
147             digitalWrite(aPin, HIGH);
148             digitalWrite(bPin, HIGH);
149             digitalWrite(cPin, HIGH);
150             digitalWrite(dPin, LOW);
151             digitalWrite(ePin, LOW);
152             digitalWrite(fPin, HIGH);
153             digitalWrite(gPin, HIGH);
154             digitalWrite(dpPin, LOW);
155             break;
156         case DECIMAL_POINT:
157             digitalWrite(aPin, LOW);
158             digitalWrite(bPin, LOW);
159             digitalWrite(cPin, LOW);
160             digitalWrite(dPin, LOW);
161             digitalWrite(ePin, LOW);
162             digitalWrite(fPin, LOW);
163             digitalWrite(gPin, LOW);
164             digitalWrite(dpPin, HIGH);
165             break;
166         default:
167             digitalWrite(aPin, LOW);
168             digitalWrite(bPin, LOW);
169             digitalWrite(cPin, LOW);
170             digitalWrite(dPin, LOW);
171             digitalWrite(ePin, LOW);
172             digitalWrite(fPin, LOW);
173             digitalWrite(gPin, LOW);
174             digitalWrite(dpPin, LOW);
175
176     }
177 }
178
179 void LEDDisplay::DisplayNumber (int number){
180
181     int temp;
182
183     // determine the digits of the number
184
185     int thousand = number/1000;
186     temp = number%1000;
187     int hundred = temp/100;
188     temp = temp%100;
189     int ten = temp/10 ;
190     temp = temp%10;
191     int unit = temp;
192
193     // determine what to display (note I cast int to Num)
194
195     if (thousand == 0){
196         if (hundred == 0){
197             if (ten == 0){
198                 digitalWrite(y1Pin, HIGH);
199                 digitalWrite(y2Pin, HIGH);
200                 digitalWrite(y3Pin, HIGH);
201                 digitalWrite(y4Pin, LOW);
202                 DisplayDigit((Num)unit);
203                 delay(5);
204             }
205             else {
206                 digitalWrite(y1Pin, HIGH);
207                 digitalWrite(y2Pin, HIGH);
208                 digitalWrite(y3Pin, LOW);
209                 DisplayDigit((Num)ten);
210                 delay(5);
211                 digitalWrite(y3Pin, HIGH);
212                 digitalWrite(y4Pin, LOW);
213                 DisplayDigit((Num)unit);
214                 delay(5);
215                 digitalWrite(y4Pin, HIGH);
216             }
217         }
218         else{
219             digitalWrite(y1Pin, HIGH);
220             digitalWrite(y2Pin, LOW);
221             DisplayDigit((Num)hundred);
222             delay(5);
223             digitalWrite(y2Pin, HIGH);
224             digitalWrite(y3Pin, LOW);
225             DisplayDigit((Num)ten);
226             delay(5);
227             digitalWrite(y3Pin, HIGH);
228             digitalWrite(y4Pin, LOW);
229             DisplayDigit((Num)unit);
230             delay(5);
231             digitalWrite(y4Pin, HIGH);
232         }
233     }
234     else{
235         digitalWrite(y1Pin, LOW);
236         DisplayDigit((Num)thousand);
237         delay(5);
238         digitalWrite(y1Pin, HIGH);
239         digitalWrite(y2Pin, LOW);
240         DisplayDigit((Num)hundred);
241         delay(5);
242         digitalWrite(y2Pin, HIGH);
243         digitalWrite(y3Pin, LOW);
244         DisplayDigit((Num)ten);
245         delay(5);
246         digitalWrite(y3Pin, HIGH);
247         digitalWrite(y4Pin, LOW);
248         DisplayDigit((Num)unit);
249         delay(5);
250         digitalWrite(y4Pin, HIGH);
251     }
252
253 }
Code for the main program:
1 /*
2 Oscar's projecthow to use 7-seg LED display
3 */
4
5 #include "Seven_Seg_LED_Display.h"
6
7 const int buttonPin = 9;     // the number of the pushbutton pin
8 int buttonState = 0;         // variable for reading the pushbutton status
9 int beingPressed = 0;        // make sure we only respond to button once when it first being pressed
10 LEDDisplay disp;             // I made a mistake declaring this inside 'loop', but in which case, it can't remember what it displayed previously
11
12 int state = 0;
13
14 void setup() {
15     // initialize the pushbutton pin as an input:
16     pinMode(buttonPin, INPUT);
17 }
18
19 void loop() {
20
21     buttonState = digitalRead(buttonPin);
22
23     /*
24     if (state == 0)
25         disp.DisplayNumber(102);
26     else
27         disp.DisplayNumber(523);
28
29     if ((buttonState == HIGH) && (beingPressed == LOW)) {
30         state++;
31     }
32     beingPressed = buttonState;
33     */
34
35     switch (state){
36         case 0:
37             disp.DisplayNumber(0);
38             break;
39         case 1:
40             disp.DisplayNumber(1234);
41             break;
42         case 2:
43             disp.DisplayNumber(523);
44             break;
45         case 3:
46             disp.DisplayNumber(70);
47             break;
48         case 4:
49             disp.DisplayNumber(3205);
50             break;
51         case 5:
52             disp.DisplayNumber(5268);
53             break;
54         case 6:
55             disp.DisplayNumber(12);
56             break;
57         case 7:
58             disp.DisplayNumber(555);
59             break;
60         default:
61             disp.DisplayNumber(8888);
62     }
63
64     if ((buttonState == HIGH) && (beingPressed == LOW)){
65         if (++state == 9)
66         state = 0;
67     }
68
69     beingPressed = buttonState;
70 }

Using switch to change display pattern of 5 LEDs

Posted on November 19, 2011 by 

5-led

In this project, I will show you how to control multiple LEDs, and use a switch button to change displaying pattern. I will also show you how to include header file to make code tidier.
Everytime button is pressed, it switches the lighting patterns. The patterns are:
0. all off
1. all on
2. one at a time and keep changing.
1 /*
2 Oscar's project
3 switch lighting patern of 5 LEDs
4
5 */
6
7 int patern = 0;
8 // 0 all off
9 // 1 all on
10 // 2 one on at a time
11
12 int onLED = 1; // which LED is on? 1-5
13 int buttonState = 0;
14
15 int iPin = 0;   // input pin
16
17 int oPin1 = 1;  // output pins
18 int oPin2 = 2;
19 int oPin3 = 3;
20 int oPin4 = 4;
21 int oPin5 = 5;
22
23 void setup() {
24     // declare pin 9 to be an output:
25     pinMode(oPin1, OUTPUT);
26     pinMode(oPin2, OUTPUT);
27     pinMode(oPin3, OUTPUT);
28     pinMode(oPin4, OUTPUT);
29     pinMode(oPin5, OUTPUT);
30
31     pinMode(iPin, INPUT);
32 }
33
34 void loop() {
35
36     buttonState = digitalRead(input);
37     if (buttonState == 1){
38         if (patern >= 2) patern = 0;
39         else patern++;
40
41         onLED = 1; // reset onLED
42         buttonState = 0;
43     }
44
45     if (patern == 0) {
46         digitalWrite(oPin1, LOW);
47         digitalWrite(oPin2, LOW);
48         digitalWrite(oPin3, LOW);
49         digitalWrite(oPin4, LOW);
50         digitalWrite(oPin5, LOW);
51     }
52     else if (patern == 1) {
53         digitalWrite(oPin1, HIGH);
54         digitalWrite(oPin2, HIGH);
55         digitalWrite(oPin3, HIGH);
56         digitalWrite(oPin4, HIGH);
57         digitalWrite(oPin5, HIGH);
58     }
59     else {
60         switch (onLED) {
61             case 1:
62             digitalWrite(oPin1, HIGH);
63             digitalWrite(oPin2, LOW);
64             digitalWrite(oPin3, LOW);
65             digitalWrite(oPin4, LOW);
66             digitalWrite(oPin5, LOW);
67             break;
68             case 2:
69             digitalWrite(oPin1, LOW);
70             digitalWrite(oPin2, HIGH);
71             digitalWrite(oPin3, LOW);
72             digitalWrite(oPin4, LOW);
73             digitalWrite(oPin5, LOW);
74             break;
75             case 3:
76             digitalWrite(oPin1, LOW);
77             digitalWrite(oPin2, LOW);
78             digitalWrite(oPin3, HIGH);
79             digitalWrite(oPin4, LOW);
80             digitalWrite(oPin5, LOW);
81             break;
82             case 4:
83             digitalWrite(oPin1, LOW);
84             digitalWrite(oPin2, LOW);
85             digitalWrite(oPin3, LOW);
86             digitalWrite(oPin4, HIGH);
87             digitalWrite(oPin5, LOW);
88             break;
89             case 5:
90             digitalWrite(oPin1, LOW);
91             digitalWrite(oPin2, LOW);
92             digitalWrite(oPin3, LOW);
93             digitalWrite(oPin4, LOW);
94             digitalWrite(oPin5, HIGH);
95             break;
96             default:
97             digitalWrite(oPin1, LOW);
98             digitalWrite(oPin2, LOW);
99             digitalWrite(oPin3, LOW);
100             digitalWrite(oPin4, LOW);
101             digitalWrite(oPin5, LOW);
102
103         }
104
105         if (onLED >= 5) onLED = 1;
106         else onLED++;
107     }
108
109     delay(30);
110 }

 

 

 

 

 

 

 

 

Learn how to use 7-Segment LED Display

Posted on November 21, 2011 by 

7-segment-display

7-Segment LED Display is a very useful component, but also a very confusing and difficult piece to use for beginners. It won’t be difficult once you get it working for the first time.

This is what you will get at the end of the tutorial (part one):

It basically consists of 7 LEDs, (8 if include decimal point). Just like controlling a single LED, we need to connect each ‘segment LED’ to a Arduino digital pin. Here is the circuit diagram of the LED display:

You might notice, there are 2 different type of them, don’t be scared by them, because in the market, the “Common Cathode” type is the most popular so you won’t need to care about the other type.
Basically, all you need to do is to connect each LED with a pin, and connect the shared Gnd connector to the ground pin. Next you will need to program it, so  required LEDs are switched on to display different number.
Here is my circuit diagram:
Coding:
I have created a class for using the 7 seg LED display, it’s not a complete working class, but gives a few very useful basic functions. Feel free to expand it and add new useful functions, or create your own class.
Seven_Seg_LED_Display.h:
1 /*
2 Oscar's project, Seven_Seg_LED Display class
3 */
4
5 #include "WProgram.h"  //standard types and constants of the Arduino language
6
7 enum Num { NOTHING = -1, ZERO = 0, ONE = 1, TWO = 2, THREE = 3, FOUR = 4, FIVE = 5,SIX = 6, SEVEN = 7, EIGHT = 8, NINE = 9, DECIMAL_POINT = 10};
8 // 10 means decimal point, -1 means nothing is being displayed
9
10 class LEDDisplay {
11
12     public:
13         Num displaying;   // indicate which number is being displayed
14
15     private:
16         int aPin;  // these are the output pins
17         int bPin;
18         int cPin;
19         int dPin;
20         int ePin;
21         int fPin;
22         int gPin;
23         int dpPin;
24
25     public:
26         LEDDisplay();  // constructor with default output pins
27         LEDDisplay(int a, int b, int c, int d, int e, int f, int g, int dp); // constructor with specified output pins
28         void DisplayNumber (Num number);
29
30 };
Seven_Seg_LED_Display.cpp:
1 /*
2 Oscar's project, Seven_Seg_LED Display class
3 */
4
5 #include "Seven_Seg_LED_Display.h"
6
7 LEDDisplay::LEDDisplay () {
8
9     displaying = NOTHING;
10
11     for (int outputPin = 1; outputPin <= 8; outputPin++)
12         pinMode(outputPin, OUTPUT);
13
14     aPin = 1;
15     bPin = 2;
16     cPin = 3;
17     dPin = 4;
18     ePin = 5;
19     fPin = 6;
20     gPin = 7;
21     dpPin = 8;
22
23 }
24
25 LEDDisplay::LEDDisplay(int a, int b, int c, int d, int e, int f, int g, intdp) {
26     displaying = NOTHING;
27
28     pinMode(aPin = a, OUTPUT);
29     pinMode(bPin = b, OUTPUT);
30     pinMode(cPin = c, OUTPUT);
31     pinMode(dPin = d, OUTPUT);
32     pinMode(ePin = e, OUTPUT);
33     pinMode(fPin= f, OUTPUT);
34     pinMode(gPin = g, OUTPUT);
35     pinMode(dpPin = dp, OUTPUT);
36
37 }
38
39 void LEDDisplay::DisplayNumber (Num number){
40
41 displaying = number;
42
43 switch (number) {
44     case ZERO:
45     digitalWrite(aPin, HIGH);
46     digitalWrite(bPin, HIGH);
47     digitalWrite(cPin, HIGH);
48     digitalWrite(dPin, HIGH);
49     digitalWrite(ePin, HIGH);
50     digitalWrite(fPin, HIGH);
51     digitalWrite(gPin, LOW);
52     digitalWrite(dpPin, LOW);
53
54     break;
55     case ONE:
56     digitalWrite(aPin, LOW);
57     digitalWrite(bPin, HIGH);
58     digitalWrite(cPin, HIGH);
59     digitalWrite(dPin, LOW);
60     digitalWrite(ePin, LOW);
61     digitalWrite(fPin, LOW);
62     digitalWrite(gPin, LOW);
63     digitalWrite(dpPin, LOW);
64     break;
65     case TWO:
66     digitalWrite(aPin, HIGH);
67     digitalWrite(bPin, HIGH);
68     digitalWrite(cPin, LOW);
69     digitalWrite(dPin, HIGH);
70     digitalWrite(ePin, HIGH);
71     digitalWrite(fPin, LOW);
72     digitalWrite(gPin, HIGH);
73     digitalWrite(dpPin, LOW);
74     break;
75     case THREE:
76     digitalWrite(aPin, HIGH);
77     digitalWrite(bPin, HIGH);
78     digitalWrite(cPin, HIGH);
79     digitalWrite(dPin, HIGH);
80     digitalWrite(ePin, LOW);
81     digitalWrite(fPin, LOW);
82     digitalWrite(gPin, HIGH);
83     digitalWrite(dpPin, LOW);
84     break;
85     case FOUR:
86     digitalWrite(aPin, LOW);
87     digitalWrite(bPin, HIGH);
88     digitalWrite(cPin, HIGH);
89     digitalWrite(dPin, LOW);
90     digitalWrite(ePin, LOW);
91     digitalWrite(fPin, HIGH);
92     digitalWrite(gPin, HIGH);
93     digitalWrite(dpPin, LOW);
94     break;
95     case FIVE:
96     digitalWrite(aPin, HIGH);
97     digitalWrite(bPin, LOW);
98     digitalWrite(cPin, HIGH);
99     digitalWrite(dPin, HIGH);
100     digitalWrite(ePin, LOW);
101     digitalWrite(fPin, HIGH);
102     digitalWrite(gPin, HIGH);
103     digitalWrite(dpPin, LOW);
104     break;
105     case SIX:
106     digitalWrite(aPin, HIGH);
107     digitalWrite(bPin, LOW);
108     digitalWrite(cPin, HIGH);
109     digitalWrite(dPin, HIGH);
110     digitalWrite(ePin, HIGH);
111     digitalWrite(fPin, HIGH);
112     digitalWrite(gPin, HIGH);
113     digitalWrite(dpPin, LOW);
114     break;
115     case SEVEN:
116     digitalWrite(aPin, HIGH);
117     digitalWrite(bPin, HIGH);
118     digitalWrite(cPin, HIGH);
119     digitalWrite(dPin, LOW);
120     digitalWrite(ePin, LOW);
121     digitalWrite(fPin, LOW);
122     digitalWrite(gPin, LOW);
123     digitalWrite(dpPin, LOW);
124     break;
125     case EIGHT:
126     digitalWrite(aPin, HIGH);
127     digitalWrite(bPin, HIGH);
128     digitalWrite(cPin, HIGH);
129     digitalWrite(dPin, HIGH);
130     digitalWrite(ePin, HIGH);
131     digitalWrite(fPin, HIGH);
132     digitalWrite(gPin, HIGH);
133     digitalWrite(dpPin, LOW);
134     break;
135     case NINE:
136     digitalWrite(aPin, HIGH);
137     digitalWrite(bPin, HIGH);
138     digitalWrite(cPin, HIGH);
139     digitalWrite(dPin, LOW);
140     digitalWrite(ePin, LOW);
141     digitalWrite(fPin, HIGH);
142     digitalWrite(gPin, HIGH);
143     digitalWrite(dpPin, LOW);
144     break;
145     case DECIMAL_POINT:
146     digitalWrite(aPin, LOW);
147     digitalWrite(bPin, LOW);
148     digitalWrite(cPin, LOW);
149     digitalWrite(dPin, LOW);
150     digitalWrite(ePin, LOW);
151     digitalWrite(fPin, LOW);
152     digitalWrite(gPin, LOW);
153     digitalWrite(dpPin, HIGH);
154     break;
155     default:
156     digitalWrite(aPin, LOW);
157     digitalWrite(bPin, LOW);
158     digitalWrite(cPin, LOW);
159     digitalWrite(dPin, LOW);
160     digitalWrite(ePin, LOW);
161     digitalWrite(fPin, LOW);
162     digitalWrite(gPin, LOW);
163     digitalWrite(dpPin, LOW);
164
165     }
166 }
The main program:
1 /*
2 Oscar's projecthow to use 7-seg LED display
3 */
4
5 #include "Seven_Seg_LED_Display.h"
6 const int buttonPin = 9;     // the number of the pushbutton pin
7 int buttonState = 0;         // variable for reading the pushbutton status
8 int beingPressed = 0;        // make sure we only respond to button once when it first being pressed
9 LEDDisplay disp;             // I made a mistake declaring this inside 'loop', but in which case, it can't remember what it displayed previously
10
11 void setup() {
12     // initialize the pushbutton pin as an input:
13     pinMode(buttonPin, INPUT);
14 }
15
16 void loop() {
17
18     /*
19     disp.DisplayNumber(TWO);
20     delay(1000);
21     disp.DisplayNumber(THREE);
22     delay(1000);
23     disp.DisplayNumber(FOUR);
24     delay(1000);
25     disp.DisplayNumber(FIVE);
26     delay(1000);
27     */
28     buttonState = digitalRead(buttonPin);
29
30     // this state is only true for one cycle at button is first pressed
31     if ((buttonState == HIGH) && (beingPressed == LOW)) {
32         switch (disp.displaying) {
33             case ZERO:
34             disp.DisplayNumber(ONE);
35             break;
36             case ONE:
37             disp.DisplayNumber(TWO);
38             break;
39             case TWO:
40             disp.DisplayNumber(THREE);
41             break;
42             case THREE:
43             disp.DisplayNumber(FOUR);
44             break;
45             case FOUR:
46             disp.DisplayNumber(FIVE);
47             break;
48             case FIVE:
49             disp.DisplayNumber(SIX);
50             break;
51             case SIX:
52             disp.DisplayNumber(SEVEN);
53             break;
54             case SEVEN:
55             disp.DisplayNumber(EIGHT);
56             break;
57             case EIGHT:
58             disp.DisplayNumber(NINE);
59             break;
60             case NINE:
61             disp.DisplayNumber(DECIMAL_POINT);
62             break;
63             case DECIMAL_POINT:
64             disp.DisplayNumber(ZERO);
65             break;
66             case NOTHING:
67             disp.DisplayNumber(ZERO);
68             break;
69             default:
70             disp.DisplayNumber(NOTHING);
71
72         }
73     }
74
75     beingPressed = buttonState;
76     delay(100);
77 }
Advertisements