Hardware components | ||||||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 4 | ||||
| × | 1 | ||||
Hand tools and fabrication machines | ||||||
|
I like engineering and Electronics and always looking to use my spare parts for something. I have accrued plenty of Arduino parts and wanted to put them to good use. A friend had a pair of helicopter APU's in the yard (as you do) and never got around to playing with them.
Time to start a new Project. With nothing but the engines I set about looking into how they operated and controlled. A strip down and re-build of one of the engines looked promising, time to dig out the Arduino's.
I could have used a more power full processor or ran off a pc but I like a challenge and what follows is the result of a year long project.
There are three parts to this project,
Firstly, the engine, this is just a bunch of servos and relays, its all down to timing each to a precise time. If you have a Jet Engine aka APU in the shed, this could be a project for you.
Secondly, connecting it together. This is the boring part but necessary, Connection pins, Layout, Heavy duty relays and a huge home made resistor but this is all dependant on the engine type and how you want to build your control unit.
Lastly, an Arduino or similar. This is where you can get creative, buttons, relays, box or container and a display. This is the bit that took the longest and I found it easier to build another box that emulates the engine, that also has an Arduino in it too.
More about the build and other stuff
USSR AI-9 (АИ-9) APU Gas Turbine (finishthoseprojects.blogspot.com)
Gas turbine APU Control Center & Diagnostic using Arduino Uno's
AI-9 Russian Gas Turbine (APU)

Finger Plate

Enclosure

Mounting Board

Main Control System
ArduinoIts basically a huge time dependant loop
I have used direct hardware ports to trigger the relay as talking to the SPI bus takes time and the Thermocouple read is slow (i may have to re look at that)
/*
AI-9 APU Gas Turbine Launch (Main Control Panel)
=====================================================================
Created 22/08/2021
by Derek Beacroft UK
// Run fuel & Ignition
// False Start Fuel No Ignition
// Cold Scroll No Fuel No Ignition
Display on I2C Line
CommandNo,"buff",Val
1,"",0 // Start
2,"",0 // Stop
3,"",0 // Reset Display
4,"message",0 // Display new message
5,
6,xxx // Temperature
7,xxx // Speed
8,
9,
10,"",01 // Over Speed
11,"",01 // Normal Speed
12,"",01 // Oil Pressure
13,"",01 // Centrifuge
14,"",01 // Boost Pump
*/
#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
// Data wire is plugged into port 3 on Arduino
#define ONE_WIRE_BUS 15 // 15=A1
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
#define Debug (bool) false //
int l_time = millis()/1000;
bool start = false;
bool R1_eMotor = false;
bool R2_eMotor = false;
bool R3_Ignition = false;
bool R4_FuelStart = false;
bool R5_FuelRun= false;
bool R6_Boost = false;
bool Sence_OpenCentrifuge =false; // eMotor Switch Nc (default open until connected to engine)
bool Sence_SpeedOk = false; // Fuel Pressure ok
bool Sence_OilOk = false; // Oil Pressure ok
bool Sence_OverSpeed = false; // Fuel Pressure over
bool ColdScroll = false;
bool FalseStart = false;
bool BtnHeld = false;
int val =0;
int Value =0;
int Sence_Temp=240;
int Btn =0;
unsigned int ReadBtn;
unsigned long c = 0;
unsigned long Temperature = 25;
long StartupDebounceTime= 0; // the last time the output pin was toggled
long lastDebounceTime = 0; // the last time the output pin was toggled
#define debounceDelay (uint8_t) 400 // the debounce time; increase if the output flickers
// constants won't change
const int PIN02_R1_eMotor1 = 2; // Start 1
const int PIN03_R2_eMotor2 = 3; // Start 2
const int PIN04_R3_Ignition = 4; // Ignition
const int PIN05_R4_StartFuel = 5; // Fuel Start
const int PIN10_R5_RunFuel = 10; // Fuel Run
const int PIN11_R6_Boost = 11; // Boost Pump
const int PIN06_Overspeed = 6; // Over Speed
const int PIN07_NormalRPM = 7; // Normal RPM
const int PIN08_NormalOil = 8; // Oil Pressure OK
const int PIN09_Centrifuge = 9; // Starter CuttOff
const int PIN12_StartBtn = 12; // START
const int PINA0_RPM = A0; // RPM
const int PINA1_Temp = A1; // Exhaust Temperature
const int PINA2_Buttons = A2; // Buttons
char newtext[]="123";
void directWrite(uint8_t pin, uint8_t value);
struct PinInfo {
volatile uint8_t *reg;
uint8_t mask;
};
const PinInfo unoPins[] = {
{&PORTD, (uint8_t) 0b11111110},
{&PORTD, (uint8_t) 0b11111101},
{&PORTD, (uint8_t) 0b11111011},
{&PORTD, (uint8_t) 0b11110111},
{&PORTD, (uint8_t) 0b11101111},
{&PORTD, (uint8_t) 0b11011111},
{&PORTD, (uint8_t) 0b10111111},
{&PORTD, (uint8_t) 0b01111111},
{&PORTB, (uint8_t) 0b11111110},
{&PORTB, (uint8_t) 0b11111101},
{&PORTB, (uint8_t) 0b11111011},
{&PORTB, (uint8_t) 0b11110111},
{&PORTB, (uint8_t) 0b11101111},
{&PORTB, (uint8_t) 0b11011111},
{&PORTC, (uint8_t) 0b11111110},
{&PORTC, (uint8_t) 0b11111101},
{&PORTC, (uint8_t) 0b11111011},
{&PORTC, (uint8_t) 0b11110111},
{&PORTC, (uint8_t) 0b11101111},
{&PORTC, (uint8_t) 0b11011111},
};
// the setup function runs once when you press reset or power the board
void setup() {
Serial.begin(115200);
//
Wire.begin(); // join i2c bus (address optional for master)
//Wire.delay(200);
sensors.begin(); // Thermocouple
pinMode(PIN02_R1_eMotor1, OUTPUT);
pinMode(PIN03_R2_eMotor2, OUTPUT);
pinMode(PIN04_R3_Ignition, OUTPUT);
pinMode(PIN05_R4_StartFuel, OUTPUT);
pinMode(PIN10_R5_RunFuel, OUTPUT);
pinMode(PIN11_R6_Boost, OUTPUT);
pinMode(PIN06_Overspeed, INPUT_PULLUP);
pinMode(PIN07_NormalRPM, INPUT_PULLUP);
pinMode(PIN08_NormalOil, INPUT_PULLUP);
pinMode(PIN09_Centrifuge, INPUT_PULLUP);
pinMode(PIN12_StartBtn, INPUT_PULLUP);
pinMode(PINA0_RPM, INPUT); // RPM
pinMode(PINA1_Temp, INPUT); // Temperature
pinMode(PINA2_Buttons, INPUT); // buttons
// initialize digital pin as an output. (Default to High will disable relay)
//digitalWrite(PIN02_R1_eMotor1, HIGH);
//digitalWrite(PIN03_R2_eMotor2, HIGH);
//digitalWrite(PIN04_R3_Ignition, HIGH);
//digitalWrite(PIN05_R4_StartFuel, HIGH);
//digitalWrite(PIN10_R5_RunFuel, HIGH);
//digitalWrite(PIN11_R6_Boost, HIGH);
directWrite(PIN02_R1_eMotor1, HIGH);
directWrite(PIN03_R2_eMotor2, HIGH);
directWrite(PIN04_R3_Ignition, HIGH);
directWrite(PIN05_R4_StartFuel, HIGH);
directWrite(PIN10_R5_RunFuel, HIGH);
directWrite(PIN11_R6_Boost, HIGH);
//const unsigned short int SW = 4;
// may only work on pin 2/3
//attachInterrupt(digitalPinToInterrupt(SW_PIN13_1), changeLock, FALLING);
//delay(1000);
//Serial.println(digitalRead(PIN06_Overspeed));
//Serial.println(digitalRead(PIN08_NormalOil));
InfoMessage("Controller Startup",true);
// default centrifuge to Nc
DisplayUpdate(13,"",0);
//
// wait for Display to Initialise
delay(5000);
//
////
//// Get any Slave data eg Version info or ready !
//Wire.requestFrom(8, 6); // request 6 bytes from slave device #8
//while (Wire.available()) { // slave may send less than requested
// char c = Wire.read(); // receive a byte as character
// Serial.print(c); // print the character
// }
}
//
// the loop function runs over and over again forever
void loop() {
//
// 1 second interval Timer
if ((((millis()-c)/1000) > l_time) && (start==false))
{
l_time=((millis()-c)/1000);
GetTemperature();
}
//
// Read Engine Sensors
// =========================================================
if (Debug==false)
{
//Sence_Temp=analogRead(PINA1_Temp);
bool BitCheck;
// Over Speed (No false)
//if (digitalRead(PIN06_Overspeed)==LOW){Sence_OverSpeed=true;} else {Sence_OverSpeed=false;}
BitCheck=digitalRead(PIN06_Overspeed);
if (BitCheck==LOW && Sence_OverSpeed==false)
{Sence_OverSpeed=true;DisplayUpdate(12,"",0);}
else if (BitCheck==HIGH && Sence_OverSpeed==true)
{Sence_OverSpeed=false;DisplayUpdate(12,"",1);}
// Normal RPM (No false)
BitCheck=digitalRead(PIN07_NormalRPM);
if (BitCheck==LOW && Sence_SpeedOk==false)
{Sence_SpeedOk=true;DisplayUpdate(11,"",0);}
else if (BitCheck==HIGH && Sence_SpeedOk==true)
{Sence_SpeedOk=false;DisplayUpdate(11,"",1);}
// Oil Pressure (No false)
BitCheck=digitalRead(PIN08_NormalOil);
if (BitCheck==LOW && Sence_OilOk==false)
{Sence_OilOk=true;DisplayUpdate(10,"",0);}
else if (BitCheck==HIGH && Sence_OilOk==true)
{Sence_OilOk=false;DisplayUpdate(10,"",1);}
// Note Cetrifuge is Fliped (Nc false)
BitCheck=digitalRead(PIN09_Centrifuge);
if (BitCheck==LOW && Sence_OpenCentrifuge==true)
{Sence_OpenCentrifuge=false;DisplayUpdate(13,"",1);}
else if (BitCheck==HIGH && Sence_OpenCentrifuge==false)
{Sence_OpenCentrifuge=true;DisplayUpdate(13,"",0);}
//
//if (Sence_SpeedOk==true) {InfoMessage("speed ok");}
//DisplayUpdate(10,"",0);
}
//
// Read Analogue Buttons
ReadBtn=analogRead(PINA2_Buttons);
//filter out any noise by setting a time buffer
//Serial.println(ReadBtn);
if ((millis() - lastDebounceTime) > debounceDelay )
{
Btn=ReadBtn;
//InfoMessage("Press " +(String)ReadBtn);
//
if (start==false)
{
//if (Btn <100) {FalseStart=false;ColdScroll=false;}
if (Btn <100 && (FalseStart==true || ColdScroll==true)){InfoMessage("Normal Start",true);FalseStart=false;ColdScroll=false;}
if (Btn >100 && Btn <300 && FalseStart==false){InfoMessage("False Start",true);FalseStart=true;ColdScroll=false;}
if (Btn >300 && Btn <500 && ColdScroll==false){InfoMessage("ColdScroll",true);FalseStart=false;ColdScroll=true;}
if (Btn >500 && Btn <750){InfoMessage("Test Spare"+(String)ReadBtn,true);}
if (Btn >750 && Btn <950)
{
//
DisplayUpdate(3,"",0) ; // Reset Display
//
Reset_Engine();
//InfoMessage("Ready",true);
start=false;
}
}
else
{
// Stop button press while starting/running
if (Btn >950)
{
c = 0;
start=false;
Shutdown();
//newtext = "ab";
//https://forum.arduino.cc/t/tricks-to-reduce-compiled-size/43560/40
InfoMessage("Stop "+(String)ReadBtn,true);
}
//Serial.println(Btn);
}
//ReadBtn=0;
lastDebounceTime = millis();
}
//
// Start Button Press for 3 sec
// ======================================================================
if (digitalRead(PIN12_StartBtn)==LOW && start == false && Sence_OverSpeed==false)
{
// add delay to allow any Analog reads to stabalise
delay(50);
//
if (BtnHeld==false){BtnHeld=true;StartupDebounceTime = millis();}
//
if ((millis() - StartupDebounceTime) > 2000 and BtnHeld==true)
{
BtnHeld=false;
StartupDebounceTime = millis();
//
c = millis(); // call before EngineReset
Reset_Engine();
//DisplayUpdate(3," ",0); // Reset Display
//
if (FalseStart==false && ColdScroll==false) {InfoMessage("Launch Start",true);}
else if (FalseStart==true) { InfoMessage("False Start",true); }
else if (ColdScroll==true) { InfoMessage("Cold Scroll",true); }
//
delay(50);
start = true;
DisplayUpdate(1,"",0);
c = millis();
//
// Boost pump is allways enabled, (notifies the diags we are running)
R6_Boost= true;
//digitalWrite(PIN11_R6_Boost, LOW);
directWrite(PIN11_R6_Boost, LOW);
DisplayUpdate(14,"",0);
InfoMessage("R6, Boost Pump On",true);
DisplayUpdate(1,"",0);
}
}
else
{
// No Press
BtnHeld=false;
//startupDebounceTime = millis();
}
//
// Engine Launch
if (start==true)
// Read Engine Sensors and Status
// =====================================================
{ // Must allways monitor for STOP press
if (analogRead(PINA2_Buttons) >950)
{
c = 0;
start=false;
Shutdown();
InfoMessage("Stop Button",true);
}
//
// Get Temperature
if ((millis() - c) == 8000){GetTemperature();}
if ((millis() - c) == 11000){GetTemperature();}
if ((((millis()-c)/1000) > l_time) && ((millis() - c) >= 15000) )
{
l_time=((millis()-c)/1000);
GetTemperature();
}
//
// Early initialisation tests
// Boost pump to pressure (5 Seconds)
if ((millis()-c) > 0 && (millis() - c) < 5000)
{
if (R6_Boost==false)
{
Reset_Engine();
InfoMessage("BoostPump Disabled",true);
}
//if (Sence_OpenCentrifuge == true)
if (Sence_OpenCentrifuge == true)
{
Reset_Engine();
InfoMessage("eMotor Centrifuge Fault",true);
}
if (Sence_OilOk == true)
{
Reset_Engine();
InfoMessage("Oil Pressure Sensor Fault",true);
}
if (Sence_SpeedOk == true)
{
Reset_Engine();
InfoMessage("Speed Sensor Fault",true);
}
if (Sence_OverSpeed == true)
{
Reset_Engine();
InfoMessage("OverSpeed Sensor Fault",true);
}
}
// Relay R1, eStart #1
if ((millis() - c) >= 5000 && (millis() - c) <= 5020)
{
// eMotor Start #1 @5 sec
if (R1_eMotor == false)
{
R1_eMotor = true;
//digitalWrite(PIN02_R1_eMotor1, LOW);
directWrite(PIN02_R1_eMotor1, LOW);
InfoMessage("R1, eMotor1 Start",false);
}
// Relay R3, Ignition
if (R3_Ignition == false && ColdScroll==false && FalseStart==false)
{
R3_Ignition = true;
//digitalWrite(PIN04_R3_Ignition, LOW);
directWrite(PIN04_R3_Ignition, LOW);
InfoMessage("R3, Ignition On",false);
}
// Relay R4 Fuel Start
if (R4_FuelStart== false && ColdScroll==false )//&& FalseStart==false
{
R4_FuelStart= true;
//digitalWrite(PIN05_R4_StartFuel, LOW);
directWrite(PIN05_R4_StartFuel, LOW);
InfoMessage("R4, Fuel Start On",false);
}
}
// Serial.println("..");
// Relay R5,Fuel Run
if ((millis() - c) >= 6000 && (millis() - c) <= 6020)
{
//Serial.println("-----------------------------------");
// Fuel run @6 sec
if (R5_FuelRun == false && ColdScroll==false)//and FalseStart==false
{
R5_FuelRun = true;
//digitalWrite(PIN10_R5_RunFuel, LOW);
directWrite(PIN10_R5_RunFuel, LOW);
InfoMessage("R5, Fuel Run On",false);
}
}
// Relay R2, Starter2
if ((millis() - c) >= 6500 && (millis() - c) <= 6520 && R2_eMotor == false)
{ // Full Amps to motor
//if (R2_eMotor == false)
// {
R2_eMotor = true;
//digitalWrite(PIN03_R2_eMotor2, LOW);
directWrite(PIN03_R2_eMotor2, LOW);
InfoMessage("R2, eMotor2 Start",false);
// }
}
// Relay R1 Starter1
if ((millis() - c) >= 6800 && R1_eMotor == true)
{
// Half motor Power Disable (Disabled to stop burnout if R2 Fails)
//if (R1_eMotor == true)
//{
R1_eMotor = false;
//digitalWrite(PIN02_R1_eMotor1, HIGH);
directWrite(PIN02_R1_eMotor1, HIGH);
InfoMessage("R1, eMotor1 Disabled",false);
//}
}
// Realy R4,Starting Fuel & Relay R3, Ignition Coil
if ((millis() - c) >= 12000)
{
if (R4_FuelStart== true)
{
// Check tart Fuel has stoped @12 sec
R4_FuelStart= false;
//digitalWrite(PIN05_R4_StartFuel, HIGH);
directWrite(PIN05_R4_StartFuel, HIGH);
InfoMessage("R4, Fuel Start Off",false);
}
if (R3_Ignition==true)
{
// Check Ignition Off @12 Sec
R3_Ignition = false;
//digitalWrite(PIN04_R3_Ignition, HIGH);
directWrite(PIN04_R3_Ignition, HIGH);
InfoMessage("R3, Ignition Shutoff",false);
}
}
//
// Constant Monitoring From Here
// ========================================================================
// Over Temperature (Any Time)
if (Sence_Temp >800 && start==true)
{
InfoMessage("Over Temperature",true);
Shutdown();
}
//
// RPM Over Speed (Any Time after 20 sec)
if ((millis() - c) >= 20000 && start==true && Sence_OverSpeed==true)
{
InfoMessage("Over Speed",true);
Shutdown();
}
// RPM not to speed after 20s
if ((millis() - c) >= 20000 && start==true && Sence_SpeedOk==false)
{
//if (digitalRead(PIN_D8_NormalOil)==LOW){InfoMessage("Oil Signal ok -------------------");}
//if (digitalRead(PIN_D7_NormalRPM)==LOW){InfoMessage("RPM Signal ok -------------------");}
InfoMessage("Low RPM Detection",true);
Shutdown();
}
// Oil Pressure Low after 24s
if ((millis() - c) >= 24000 && start==true && Sence_OilOk==false && Sence_SpeedOk==true)
{
//if (digitalRead(PIN_D8_NormalOil)==LOW){InfoMessage("Oil Signal ok -------------------");}
//if (digitalRead(PIN_D7_NormalRPM)==LOW){InfoMessage("RPM Signal ok -------------------");}
InfoMessage("Oil Pressure Low",true);
Shutdown();
}
// Sence_OpenCentrifuge after 20s
if ((millis() - c) >= 20000 && start==true && Sence_OpenCentrifuge==false)
{
InfoMessage("eMotor Centrifuge Error",true);
Shutdown();
}
// Stop motor if centrifuge after 12s or max >20s
if ((millis() - c) >= 12000 && Sence_OpenCentrifuge==true && R2_eMotor==true && start==true)
{
R2_eMotor =false;
//digitalWrite(PIN03_R2_eMotor2, HIGH);
directWrite(PIN03_R2_eMotor2, HIGH);
InfoMessage("eMotor2 disconnect",true);
}
if ((millis() - c) >= 20000 && start==true && R2_eMotor ==true)
{
R2_eMotor =false;
//digitalWrite(PIN03_R2_eMotor2, HIGH);
directWrite(PIN03_R2_eMotor2, HIGH);
InfoMessage("eMotor2 disconnect",true);
}
}
// End Of Loop
}
bool GetTemperature()
{
sensors.requestTemperatures(); // Send the command to get temperatures
Sence_Temp=sensors.getTempCByIndex(0);
DisplayUpdate(6,"",Sence_Temp);
}
bool Shutdown()
{
c = 0;
Reset_Engine();
DisplayUpdate(2," ",0); // Stop Timer
}
bool Reset_Engine()
{
// Shutdown Engine
start = false;
//c = 0;
//Sence_Temp=0;
Sence_OverSpeed = false;
Sence_SpeedOk = false;
Sence_OilOk = false;
Sence_OpenCentrifuge =false;
directWrite(PIN02_R1_eMotor1, HIGH); R1_eMotor = false;
directWrite(PIN03_R2_eMotor2, HIGH); R2_eMotor = false;
directWrite(PIN04_R3_Ignition, HIGH); R3_Ignition = false;
directWrite(PIN05_R4_StartFuel, HIGH); R4_FuelStart = false;
directWrite(PIN10_R5_RunFuel, HIGH); R5_FuelRun = false;
directWrite(PIN11_R6_Boost, HIGH); R6_Boost =false;
// reset of display will clear all sensors
//DisplayUpdate(3,"",0) ;
delay(200);
InfoMessage("Engine Reset",false);
return true;
}
//
//
void InfoMessage(String NewText,boolean Display)
{
//Serial.println( (String) (millis() - c) +":" +NewText);
//
//DisplayUpdate(4,NewText,0) ; // 4 Message out to Display
if (Display==true)
{
// TFT output
DisplayUpdate(4,NewText,0) ; // 4 Message out to Display
}
else
{
// Debug only
Serial.println(NewText);
}
}
//
//https://docs.arduino.cc/library-examples/wire-library/ControllerWriter
void DisplayUpdate(int CommandNo,String Buffer,int Val)
{
int mask = 0xFF;
Serial.println("Command:" +(String)CommandNo+ " "+Buffer +" "+(String)Val);
//return;
Wire.beginTransmission(8); // transmit to device #8
Wire.write(CommandNo); // sends one byte Command 1-255
Wire.write(Buffer.c_str()); // Send Buffer
//Wire.write(""); // Terminate Buffer with ""
Wire.write(Val & mask); // sends one byte Val
Wire.write(Val >>8); // sends one byte Val
Wire.endTransmission(); // stop transmitting
//Serial.println("Done");
}
void setpin(int Pin)
{
//https://arduino.stackexchange.com/questions/44531/arduino-esp8266-direct-fast-control-of-the-digital-pins
bitSet(PORTD,Pin);
bitSet(PORTD,Pin);
bitSet(PORTD,Pin);
bitSet(PORTD,Pin);
}
void directWrite(uint8_t pin, uint8_t value) {
if (value == 0) {
*(unoPins[pin].reg) &= unoPins[pin].mask;
} else {
*(unoPins[pin].reg) |= ~unoPins[pin].mask;
}
}
Display Controler
ArduinoAnd before im flooded with "why not do it this way" etc, its because i did and i do it for pleasure.
/*
AI-9 APU Gas Turbine Display
=====================================================================
Created 22/08/2021
by Derek Beacroft
Display on I2C Line
CommandNo,"buff",Val
1,"",0 // Start
2,"",0 // Stop
3,"",0 // Reset Display
4,"message",0 // Display new message
5,
6,xxx // Temperature
7,xxx // Speed
8,
9,
10,"",01 // Over Speed
11,"",01 // Normal Speed
12,"",01 // Oil Pressure
13,"",01 // Centrifuge
14,"",01 // Boost Pump
free 399
*/
#include <Wire.h>
//
//
#include <LCDWIKI_GUI.h> //Core graphics library
#include <LCDWIKI_SPI.h> //Hardware-specific library
//paramters define
#define MODEL ILI9488_18
//
#include <arduino-timer.h>
//auto timer = timer_create_default(); // create a timer with default settings
//https://www.forward.com.au/pfod/ArduinoProgramming/SafeString/index.html
//#define CS A2
//#define CD A3
//#define RST A1
//#define LED A0 //if you don't need to control the LED pin,you should set it to -1 and set it to 3.3V
#define CS A2
#define CD A0
#define RST A1
#define LED A3 //if you don't need to control the LED pin,you should set it to -1 and set it to 3.3V
#define Rad (float) 0.01745329
unsigned long RunTime = 0;
bool SystemRun = false;
bool Dev = false;
//the definiens of hardware spi mode as follow:
//if the IC model is known or the modules is unreadable,you can use this constructed function
LCDWIKI_SPI my_lcd(MODEL,CS,CD,RST,LED); //model,cs,dc,reset,led
//define some colour values
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
//#define Op (String) "Oil Pressure:"
//#define Space (String) " "
int Tm;
int Ts;
int TempPointer = 300; // Initial point of Temp gauge
//bool Ready = false; // Display Initialised and Ready
bool DisplayReady = false; // Display Initialised and Ready
String Line1="";
String Line2="";//"Initialising";
//String Line3="AI-9 Control v1.0";
String Line3="";
String Line4="";
//String Line5="";
//char abc(20);
void setup() {
//
//pinMode(LED, OUTPUT); // TFT Backlite
//analogWrite(LED, 250); // Power level (Max 3v)
Serial.begin(115200); // start serial for output
//
Wire.begin(8); // join i2c bus with address #8
//Wire.onRequest(requestEvent); // register outgoung event
Wire.onReceive(receiveEvent); // register incommong event
my_lcd.Init_LCD();
my_lcd.Fill_Screen(0x0);
//Serial.println("Init");
my_lcd.Led_control(true);
//
// left,top,left+,right+
//mylcd.Fill_Screen(BLACK);
my_lcd.Set_Rotation(1);
my_lcd.Set_Text_Back_colour(BLACK);
my_lcd.Set_Text_colour(0xE000);
//my_lcd.Print_String("Initialising AI-9", 10, 10);
my_lcd.Set_Text_Size(4);
my_lcd.Print_String("RUN TIME", 10, 10);
my_lcd.Set_Text_Size(5);
my_lcd.Print_String("00:00", 30, 55);
my_lcd.Set_Text_Size(2);
my_lcd.Draw_Rectangle( 0, 0, 477, 317);
my_lcd.Draw_Rectangle( 1, 1, 476, 316);
my_lcd.Draw_Rectangle( 2, 2, 475, 315);
my_lcd.Draw_Rectangle( 30, 140, 450, 141);
my_lcd.Print_String("Oil Pressure", 270, 15);
my_lcd.Draw_Rectangle( 430, 10, 460, 30);
my_lcd.Print_String("Normal Speed", 270, 40);
my_lcd.Draw_Rectangle( 430, 35, 460, 55);
my_lcd.Print_String("Over Speed", 290, 65);
my_lcd.Draw_Rectangle( 430, 60, 460, 80);
my_lcd.Print_String("Centrifuge", 290, 90);
my_lcd.Draw_Rectangle( 430, 85, 460, 105);
my_lcd.Print_String("Pump:", 280, 115);
my_lcd.Draw_Rectangle( 430, 110, 460, 130);
my_lcd.Print_String("Telemetry", 10, 150);
my_lcd.Draw_Rectangle( 10, 170, 260, 300);
//
// Add Startup Initalising text
//DisplayMessage("");
//
// Temp 0 to 900 deg
my_lcd.Draw_Circle(365,230,18);
my_lcd.Draw_Circle(365,230,50);
my_lcd.Draw_Circle(365,230,70);
//
my_lcd.Set_Text_Size(1);
my_lcd.Print_String("0", 280, 250);
my_lcd.Print_String("200", 370, 150);
my_lcd.Print_String("650", 440, 210);
my_lcd.Print_String("830", 420, 280);
my_lcd.Print_String("1000", 345, 305);
my_lcd.Draw_Rectangle( 10, 170, 260, 300);
//my_lcd.Draw_Line(365,260,365,300);
// (x,y) = (12*sin(115), 12*cos(115))
//my_lcd.Draw_Line(30*sin(Deg)+365,30*cos(Deg)+230,70*sin(Deg)+365,70*cos(Deg)+230);
my_lcd.Set_Draw_color(RED);
for (float T = 0; T<300; T+=1)
{
//my_lcd.Draw_Line((30*sin(T*Rad ))+365,(30*cos(T*Rad))+230,(70*sin(T*Rad))+365,(70*cos(T*Rad))+230);
my_lcd.Draw_Line((50*sin(T*Rad ))+365,(50*cos(T*Rad))+230,(69*sin(T*Rad))+365,(69*cos(T*Rad))+230);
if ( T ==50)my_lcd.Set_Draw_color(GREEN);
if ( T ==100)my_lcd.Set_Draw_color(BLUE);
//if ( T ==150)my_lcd.Set_Draw_color(RED);
//Serial.println((String) (T) +" x:"+(String) ((30*sin(T*Rad))) + " y:"+ (String) ((30*cos(T*Rad))) + " :" + (String) (sin(T*Rad)) );
//(30*sin(T))+365,(30*cos(T))+230,(70*sin(T))+365,(70*cos(T))+230)
}
my_lcd.Set_Draw_color(RED);
my_lcd.Draw_Line((46*sin(50*Rad ))+365,(46*cos(50*Rad))+230,(49*sin(50*Rad))+365,(49*cos(50*Rad))+230);
my_lcd.Draw_Line((46*sin(100*Rad ))+365,(46*cos(100*Rad))+230,(49*sin(100*Rad))+365,(49*cos(100*Rad))+230);
my_lcd.Draw_Line((46*sin(150*Rad ))+365,(46*cos(150*Rad))+230,(49*sin(150*Rad))+365,(49*cos(150*Rad))+230);
my_lcd.Draw_Line((46*sin(200*Rad ))+365,(46*cos(200*Rad))+230,(49*sin(200*Rad))+365,(49*cos(200*Rad))+230);
my_lcd.Draw_Line((46*sin(250*Rad ))+365,(46*cos(250*Rad))+230,(49*sin(250*Rad))+365,(49*cos(250*Rad))+230);
my_lcd.Draw_Line((46*sin(300*Rad ))+365,(46*cos(300*Rad))+230,(49*sin(300*Rad))+365,(49*cos(300*Rad))+230);
//uint16_t x,y;
//x=10;
//y=100;
//
// for (int16_t row = 0; row < 200; row++)
// {
// my_lcd.Read_GRAM(x, y + row, buf,wid, 1);
// my_lcd.Set_Addr_Window(x, y + row, x + wid - 1, y + row);
// my_lcd.Push_Any_Color(buf + dx, wid - dx, 1,0);
// my_lcd.Push_Any_Color(buf + 0, dx, 0,0);
// }
//
//
timer.every(1000, DisplayTime);
//
// Display layout Initalised, allow messages
DisplayReady=true;
//
// Move Temperature Display
for (float T = 1000; T>=0; T-=8)
{DisplayTemperature(T);}
//DisplayTemperature(0);
// my_lcd.Set_Text_colour(WHITE);
// TempPointer=0;
// my_lcd.Set_Draw_color(WHITE);
// my_lcd.Draw_Line((20*sin(300*Rad ))+365,(20*cos(300*Rad))+230,(45*sin(300*Rad))+365,(45*cos(300*Rad))+230);
// my_lcd.Draw_Line((20*sin(299*Rad ))+365,(20*cos(299*Rad))+230,(45*sin(299*Rad))+365,(45*cos(299*Rad))+230);
//my_lcd.Fill_Triangle(50,50,75,25,100,50);
//my_lcd.Draw_Triangle
// my_lcd.Fill_Triangle(my_lcd.Get_Display_Width()/2-1,my_lcd.Get_Display_Height()/2-1-i,
// my_lcd.Get_Display_Width()/2-1-i,my_lcd.Get_Display_Height()/2-1+i,
// my_lcd.Get_Display_Width()/2-1+i,my_lcd.Get_Display_Height()/2-1+i);
//my_lcd.Set_Text_colour(WHITE);
//
//
//RunTime = millis(); // call before Start
}
//
// the loop function runs over and over again forever
// ========================================================================
void loop() {
// abc='Oil Pressure';
// my_lcd.Print_String(abc, 270, 15);
//if (SystemRun == true) { DisplayTime();}
// if (((millis()-c)/1000) > l_time)
// {}
timer.tick(); // tick the timer
// if (millis()/1000 ==15) SetSensor(1,true);
// if (millis()/1000 ==20) SetSensor(1,false);
//
// if (millis()/1000 ==15) SetSensor(3,true);
// if (millis()/1000 ==30) SetSensor(3,false);
//
// DisplayMessage((String) millis());
// Serial.println((String) millis());
//uint16_t scrollbuf[my_lcd.Get_Display_Height()];
//
// for (int16_t i = my_lcd.Get_Display_Width(), dx = 4, dy = 0; i > 0; i -= dx)
// {
// windowScroll(0, 216, my_lcd.Get_Display_Width(), 16, dx, dy, scrollbuf);
// }
}
////
//// function that executes whenever data is requested by master
//// this function is registered as an event, see setup()
//void requestEvent() {
//
//
//
// Wire.write("Mooo- "); // respond with message of 6 bytes
// // as expected by master
//
//
//}
// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany)
{
//
// protocol
// Start 1,"buff",0
// Stop 2,"",0
// Reset 3,"",0
// Message 4,"String,0/1
// Sensor 5,"T/F",x
// Temp 6,"",X
// Speed 7,"",X
String InBuff="";
//
// Get command Identifier 00 to 15
int Command = Wire.read();
if (Command >0 and Command<20) {
while(2 < Wire.available()) // loop through all but the last 3
{
char c = Wire.read(); // receive byte as a character
InBuff+=c;
//if (c==","){InBuff="";}
//else if() {In+=c}
//Command+=c; // build command
//Serial.print(c); // print the character
}
//
//Wire.read(); // read string terminator
//Wire.read(); // read a seperator
//int InVal1 = Wire.read(); // read string terminator
//int InVal2 = Wire.read(); // read a seperator
int InVal2 = Wire.read(); // read last char
int InVal3 = Wire.read(); // read last char
int InVal= (InVal3 << 8)+InVal2;
//
// if this worked i should have all parts
//Serial.println("Incomming bytes:" + (String) howMany);
//
// if display is not read skip the incomming update
if (DisplayReady==true)
{
//if (Dev==true) {Serial.println("Command:" + (String) Command +" Val:"+(String)InVal);};
//if (Dev==true) {Serial.println("Command:" + (String) Command +" Val:"+(String)InVal2+" Val:"+(String)InVal3);};
switch (Command) {
case 1: // Start timer
//RunTime=0;
RunTime=millis();
SystemRun=true;
break;
case 2: // Stop timer
//RunTime=0;
SystemRun=false;
break;
case 3: // Reset all info
RunTime=0; // Resets Clock on Display
SystemRun=true; // forces clock update to 00:00
DisplayTemperature(0); // Reset Temperature until next update
DisplayClear(); //
UpdateSensor(0,false); // Oil Pressure
UpdateSensor(1,false); // Normal Speed
UpdateSensor(2,false); // Over Speed
UpdateSensor(3,true); // Centrifuge
UpdateSensor(4,false); // Boost Pump
break;
case 4: // Display Message
if (InBuff.length() >=4 and InBuff.length() <=20)
DisplayMessage(InBuff);
break;
// case 5: //DisplayMessage(InBuff);
// if (InBuff=="true")
// {UpdateSensor(InVal,true);}
// else
// {UpdateSensor(InVal,false);}
// break;
case 6: // Temperature
DisplayTemperature(InVal);
break;
case 7: // Speed Not Used Yet
DisplaySpeed(InVal);
break;
// case 8:
// case 9:
case 10: // Sensor 0 Overspeed
if (InVal==0)
{UpdateSensor(0,true);}
else
{UpdateSensor(0,false);}
break;
case 11: // Sensor 1 Norm RPM
if (InVal==0)
{UpdateSensor(1,true);}
else
{UpdateSensor(1,false);}
break;
case 12: // Sensor 2 Oil
if (InVal==0)
{UpdateSensor(2,true);}
else
{UpdateSensor(2,false);}
break;
case 13: // Sensor 3 centrifuge
if (InVal==0)
{UpdateSensor(3,true);}
else
{UpdateSensor(3,false);}
break;
case 14: // Sensor 4 pump
if (InVal==0)
{UpdateSensor(4,true);}
else
{UpdateSensor(4,false);}
break;
default:
// Nothing to do
break;
}
}
}
}
//
// Right hand Pressure sensors
void UpdateSensor(int SwitchNo,bool Sensor)
{
if (Sensor== true)
{my_lcd.Fill_Rect( 432,(SwitchNo*25)+12,27,17, RED );}
else
{my_lcd.Fill_Rect( 432,(SwitchNo*25)+12,27,17, BLACK );}
}
//
// Poss RPM Sensor display
void DisplaySpeed(int NewSpeed)
{
// ToDo
}
//
// Temperature Pointer display
void DisplayTemperature(int NewTemp)
{
//
if (Dev==true) {Serial.println("Temp:" + (String)NewTemp);};
//Temp Range 0-1000
NewTemp=((NewTemp/3.33)-300)*-1;
if (DisplayReady==true)
{
//
DisplayReady=false;
//
//
if (TempPointer != NewTemp) {
// Clear Old
my_lcd.Set_Draw_color(BLACK);
my_lcd.Draw_Line((20*sin(TempPointer*Rad ))+365,(20*cos(TempPointer*Rad))+230,(45*sin(TempPointer*Rad))+365,(45*cos(TempPointer*Rad))+230);
my_lcd.Draw_Line((20*sin((TempPointer-1)*Rad ))+365,(20*cos((TempPointer-1)*Rad))+230,(45*sin((TempPointer-1)*Rad))+365,(45*cos((TempPointer-1)*Rad))+230);
//my_lcd.Fill_Triangle(0, y0, x1, y1, x2, y2)
// Show New
my_lcd.Set_Draw_color(WHITE);
my_lcd.Draw_Line((20*sin(NewTemp*Rad ))+365,(20*cos(NewTemp*Rad))+230,(45*sin(NewTemp*Rad))+365,(45*cos(NewTemp*Rad))+230);
my_lcd.Draw_Line((20*sin((NewTemp-1)*Rad ))+365,(20*cos((NewTemp-1)*Rad))+230,(45*sin((NewTemp-1)*Rad))+365,(45*cos((NewTemp-1)*Rad))+230);
// Save Current Pointer
TempPointer=NewTemp;
}
//
DisplayReady=true;
}
}
void DisplayClear()
{ // should we wait for DisplayReady ??
//Line1="";Line2="";Line3="";
//my_lcd.Set_Text_colour(BLACK);
//my_lcd.Draw_Rectangle( 10, 170, 260, 300);
//my_lcd.Fill_Rect( 10,170,260,300, BLACK );
DisplayMessage("");
DisplayMessage("");
DisplayMessage("");
DisplayMessage("Reset");
}
void DisplayMessage(String Message)
{
if (DisplayReady==true)
{
//
DisplayReady=false;
my_lcd.Set_Text_Size(2);
my_lcd.Set_Text_colour(BLACK);
my_lcd.Print_String(Line1, 15, 192);
my_lcd.Set_Text_colour(WHITE);
my_lcd.Print_String(Line2, 15, 192);
my_lcd.Set_Text_colour(BLACK);
my_lcd.Print_String(Line2, 15, 212);
my_lcd.Set_Text_colour(WHITE);
my_lcd.Print_String(Line3, 15, 212);
my_lcd.Set_Text_colour(BLACK);
my_lcd.Print_String(Line3, 15, 232);
my_lcd.Set_Text_colour(WHITE);
my_lcd.Print_String(Line4, 15, 232);
my_lcd.Set_Text_colour(BLACK);
my_lcd.Print_String(Line4, 15, 252);
my_lcd.Set_Text_colour(WHITE);
my_lcd.Print_String(Message, 15, 252);
//
// my_lcd.Set_Text_colour(BLACK);
// my_lcd.Print_String(Line5, 15, 282);
// my_lcd.Set_Text_colour(WHITE);
// my_lcd.Print_String(Message,15, 282);
Line1=Line2;
Line2=Line3;
Line3=Line4;
Line4=Message;//Line5;
//Line5=Message;
if (Dev==true) {Serial.println(Message);};
DisplayReady=true;
}
}
void DisplayTime()
{
int TxtColour = 0xE000;
String Out ="";
if (SystemRun==true) //or (SystemRun==false and RunTime>0))
//if (DisplayReady==true)
{
//
//DisplayReady=false;
//
if (RunTime ==0)
{
Out ="00:00";
//my_lcd.Set_Text_colour(0xE000);
SystemRun=false;
}
else
{
Out="";
Ts=((millis()-RunTime)/1000);
Tm=(Ts/60);
Tm= Tm-((Tm/60)*60);
if (Tm>=60) Tm=0;
if (Tm<10) Out ="0";
Out+=(String)Tm +":";
Ts= Ts-((Ts/60)*60);
if (Ts<10) Out +="0";
Out+=(String)Ts;
TxtColour =WHITE;
}
//
my_lcd.Set_Text_colour(TxtColour);
my_lcd.Set_Text_Size(5);
my_lcd.Print_String(Out , 30, 55);
//if (Dev==true) {Serial.println("time :" + Out);};
}
//
}
//
//
//void windowScroll(int16_t x, int16_t y, int16_t wid, int16_t ht, int16_t dx, int16_t dy, uint16_t *buf)
//{
// if (dx)
// {
// for (int16_t row = 0; row < ht; row++)
// {
// my_lcd.Read_GRAM(x, y + row, buf,wid, 1);
// my_lcd.Set_Addr_Window(x, y + row, x + wid - 1, y + row);
// my_lcd.Push_Any_Color(buf + dx, wid - dx, 1,0);
// my_lcd.Push_Any_Color(buf + 0, dx, 0,0);
// }
// }
// if (dy)
// {
// for (int16_t col = 0; col < wid; col++)
// {
// my_lcd.Read_GRAM(x + col, y, buf,1, ht);
// my_lcd.Set_Addr_Window(x + col, y, x + col, y + ht - 1);
// my_lcd.Push_Any_Color(buf + dy, ht - dy, 1,0);
// my_lcd.Push_Any_Color(buf + 0, dy, 0,0);
// }
// }
//}
//
//
//draw some filled triangles
void fill_triangles_test(void)
{
int y0 = 0;
int y2 = 0;
int i = 0;
my_lcd.Fill_Screen(BLACK);
for(i=my_lcd.Get_Display_Width()/2-1;i>0;i-=5)
{
my_lcd.Set_Draw_color(0,i+64,i+64);
my_lcd.Fill_Triangle(my_lcd.Get_Display_Width()/2-1,my_lcd.Get_Display_Height()/2-1-i,
my_lcd.Get_Display_Width()/2-1-i,my_lcd.Get_Display_Height()/2-1+i,
my_lcd.Get_Display_Width()/2-1+i,my_lcd.Get_Display_Height()/2-1+i);
my_lcd.Set_Draw_color(i,0,i);
my_lcd.Draw_Triangle(my_lcd.Get_Display_Width()/2-1,my_lcd.Get_Display_Height()/2-1-i,
my_lcd.Get_Display_Width()/2-1-i,my_lcd.Get_Display_Height()/2-1+i,
my_lcd.Get_Display_Width()/2-1+i,my_lcd.Get_Display_Height()/2-1+i);
}
}
Comments