DIY Arduino Tachometer for your RC Airplane

The Project

To properly tune a small gas airplane engine, a tach is essential. I was just going to buy a tower hobbies tachometer for tuning my new Yak 54 gas RC airplane, but instead I spent an entire day build my own, and you can too!

There are some good products out there that work, but you don't have the sastifaction of making it yourself.

This will show you how to build your own with hopefully a lot less time than it took me. Also, once you get a ground unit working well, you can add an airplane unit and get RPM telemetry when you are flying, but we will leave that for another day.

The ardupilot documentation has a nice overview of what the software is doing, but we are using an IR sensor instead of a hall effect sensor which requires a magnet, but has less noise.

I roughly followed this tutorial to create mine

The library for the OLED is here

The sensor is not perfect and has about 500-1000 RPMs of noise, which isn't great but not sure how you make it better. One thing I noticed is that if you point the IR transmitter and reciever in a little there seems to be less noise.

Materials

Images

Wiring Diagram

/files/diy-arduino-tachometer-for-your-rc-airplane/gallery/Propellor_Tachometer_Using_Arduino_Wiring_Diagram.jpg

Finished!

Everything is soldered together and ready to test.

/files/diy-arduino-tachometer-for-your-rc-airplane/gallery/finished_tach2.jpg

I mounted everything on a piece of balsa wood and added shrink wrap for durability. The battery is simply taped on for easy changing.

/files/diy-arduino-tachometer-for-your-rc-airplane/gallery/mounted_tach_screen.jpg

/files/diy-arduino-tachometer-for-your-rc-airplane/gallery/mounted_tach_battery.jpg

The code

/*
PropTach v0.2
Neal Gordon
*/
// Import OLED library
#include <Arduino.h>
#include <U8x8lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
// The complete list is available here: https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);
// The number of blades on the propeller. Adjust accordingly.
const unsigned int BLADE_COUNT = 2;
// Volatile keyword is used with interrupts
// This variable is subject to change inside an interrupt
// service routine
volatile unsigned int myinterrupts = 0;
unsigned int myinterrupts_print;
// Used for capturing the rpm (revolutions per minute)
unsigned int rpm;
unsigned int rpm_print;
void setup()
     {
     Serial.begin(9600);
     u8x8.begin();
     u8x8.setPowerSave(0);
     u8x8.setFont(u8x8_font_amstrad_cpc_extended_r);  // u8x8_font_amstrad_cpc_extended_r , u8x8_font_chroma48medium8_r
     // u8x8_font_amstrad_cpc_extended_f
     // u8x8_font_chroma48medium8_r
     u8x8.drawString(0,0,"PropTach v0.2");  // line 0
     u8x8.drawString(0,1,"-------------");  // line 1
     u8x8.drawString(0,2,"Blades");         // line 2
     u8x8.setCursor(0, 3);                  // line 3
     u8x8.print(BLADE_COUNT);               // line 3
     u8x8.drawString(0,5,"RPM");            // line 4
     u8x8.drawString(0, 6, "     ");
     // The Infrared phototransistor is connected to pin 2.
     // Interrupt triggers when signal goes from HIGH to LOW
     // on pro mini arduino must use pins 2 or 3 for interrupts
     // file:///C:/Program%20Files%20(x86)/Arduino/reference/www.arduino.cc/en/Reference/AttachInterrupt.html
     attachInterrupt(digitalPinToInterrupt(3), isr_break_count, FALLING);
     }
void isr_break_count()
     {
     myinterrupts++;
     }
// the loop routine runs over and over again forever:
void loop()
     {
     // Update time and rpm every second
     delay(300);
     // Don't process interrupts during this calculation
     noInterrupts();
     // Calculate the RPM. If a 3-blade propeller, 3 breaks
     // per second would yield 1 rpm, which is 60 rpm.
     rpm = (60 * myinterrupts) / BLADE_COUNT;
     rpm_print = rpm;
     myinterrupts_print = myinterrupts;
     myinterrupts = 0;
     rpm = 0;
     // Restart interrupts
     interrupts();
     //  Serial.print("interrupts: ");
     //  Serial.print(myinterrupts_print);
     //  Serial.print("\t");
     Serial.print("rpm: ");
     Serial.print(rpm_print);
     Serial.print("\t");
     Serial.print("\r\n");
     u8x8.drawString(0, 6, "     ");
     u8x8.drawString(0, 6, String(rpm_print).c_str());
     }

Stay Curious!

Comments

Comments powered by Disqus