Chuck Miller
Published © GPL3+

Aircraft Engine Preheater Remote Controller

Remote programmable AC outlet (connected to engine heater) controller using SMS, with temp sensor.

IntermediateFull instructions provided4 hours1,516
Aircraft Engine Preheater Remote Controller

Things used in this project

Hardware components

Raspberry Pi Zero
Raspberry Pi Zero
×1
Hologram Nova
Hologram Nova
This is an excellent cellular device. You will also require a SIM card.
×1
Hologram Global IoT SIM Card
Hologram Global IoT SIM Card
Their SIM card works well. They are a bit expensive at $.20 per MO (Mobile Originated, returned ), but no coast for MT ( Mobile Terminated, outbound)
×1
5-12V TTL Signal 1 Channel Module High Level Expansion Board For Arduino
×1
Resistor 4.75k ohm
Resistor 4.75k ohm
×1
Temperature Sensor
Temperature Sensor
×1
Micro USB to usb(female) cable. ( to attach Cellular radio to Pi Zero)
From Amazon: CableCreation Micro USB 2.0 OTG Cable Flat On The Go Adapter Micro USB Male to USB Female, 6 Inch, Black
×1

Story

Read more

Schematics

Heater (AC outlet) Controller

This is the schematic for the controller

Heater

Code

Heater Code

Python
This is the complete code file for the controller
#This is my first Python program, so you folks who know Python well will most likley wonder why I do some of the things I did,the way I did them......... I don't know any better :)
#This is SMS based because I wanted to be able to control the device from any type of phone ( no app required)
# The commands are sent as  CMD xyyy.  the CMD must be the first three charactures followed by a space, then four digits. x=the Mode, and yyy is the data. This is detailed in the code below.
#The one item that you will need to complete the project is a sim card for the radio, and it's associated "phone" number. I used a Hologram sim. I used their easy tool kit and with a few commands, got it
#to send an sms from the Nova to my phone, thus capturing the phone number.
# to make it run at boot-up, type:
#sudo nano /etc/rc.local
#this will open the editor. Insert:
#    sudo python /home/pi/python_games/Heatercode.py &   
#NOTE: the program name will be yours. 
#
#   exit 0
#save it. Make sure you run the pi config and make tho boot up to the command prompt and dnot the GUI desktop. You can always type startx to bring up the desktop.
# Well, that's about it. Feel free to ask any questions. I can't guarantee I will have the answer, but I'll try.. :-)
# Oh, one last note. The relay is a single pole device. I used and inexpensive , 3 wire, extenstion coard. Make sure you break the "hot" (usually the black) wire with the relay. If no black, it will be the wire that connects to
# the smaller of the two blades on the plug.

import serial   #this is the serial package that allows us to chat with the USB radio as a serial device.
import time    # basic time functions
import os
import glob
import RPi.GPIO as GPIO  #access to the IO pins
Minut = 0
GPIO.setwarnings(False)
Relay = 11
GPIO.setmode(GPIO.BOARD)
GPIO.setup(Relay, GPIO.OUT)
COMMAND = 0
Phnumber = 0
Action = 1
Msg = 0
Mode = 8
sentflag = 1
Timer = 0
Stime = 0
HighTemp = 55 # initial hightemp setting F
SendFlag=0
Temp = 0
TEST = 0    # if test = 1 then the device will NOT return SMS.This is to reduce cost. Strictly a test function.
TMode = 0
dret = "ON"
SigLevel = 0
remaining = 0
RelayFlag =0
Help = 0
os.system("modprobe w1-gpio") #this sets the i/o for the temp sensor
os.system("modprobe w1-therm")
base_dir = "/sys/bus/w1/devices/"
device_folder = glob.glob(base_dir+"28*")[0]
device_file=device_folder+"/w1_slave"

#this proceedure returns the device temperture  when called
#it will detect the DS18B20 sensor ID and retrieve the raw temperature
#thanks to Adafruit folks for the heart of this temperature proceedure
def read_temp_raw():
       f=open(device_file,"r")
       lines = f.readlines()
       f.close
       return lines
 
def read_temp():
       lines= read_temp_raw()
       while lines[0].strip()[-3:] !="YES":
              time.sleep(0.2)
              lines= temp_raw()
       temp_output = lines[1].find("t=")
       if temp_output != -1:
              temp_string = lines[1].strip()[temp_output+2:]
              temp_c = int (temp_string) / 1000.0
              temp_f = int (temp_c * 9 / 5 + 32)
              Temp = temp_f
              return temp_f 
ser = serial.Serial("/dev/ttyACM2",  baudrate=38400, timeout=1)  #this sets the serial com for the Nova Radio
#time.sleep(30)
#this are the AT commands that set the radio and the SMS format. The documtation from the Halo folks is excellent. You can look up the commands easily. :)
ser.write("\x1a") #this is to flush any SMS that was lingering in the radio
ser.write("AT\r")
time.sleep(1)
ser.write("AT\r")
time.sleep(1)
ser.write("at+creg?\r\n")
rcs = ser.read(100)
print (rcs)
ser.write("at+csms=1\r")
rcs = ser.read(50)
print rcs
time.sleep(.1)
ser.write("at+cfun=1\r")
time.sleep(.1)
ser.write("at+cmgf=1\r")
time.sleep(.1)
ser.write("ate0\r\n")
time.sleep(.1)
ser.write("at+cfun=1\r")
time.sleep(.1)
ser.write("at+cpms=\"sm\",\"sm\",\"sm\"\r") 
time.sleep(.5)
ser.write("at+cnmi=1,0,0,0\r")
time.sleep(.1)    
ser.write("at+cmgr=1\r")  
rcs = ser.read(150)
Tres = len(rcs)

startime = time.time()  #this starts our basic time keeping 
while True:
       ser.write("at\r")  #Just a basic AT wakeup command
       time.sleep(.5)
       ser.write("at+cpms?\r") #ask the radio for the status of message storage.( have we received any SMS)
       rcs = ser.read(150)
       ind = rcs.find("CPMS:") # ind will contain the number of SMS's received
       if ind >= 2:       
              print "ind:",int(ind)
              print "RCS",rcs[ind+11]
              print (rcs)
       try:
              print "Point A:",rcs[ind+11]
       except IndexError:
              print "oops!"
              ser.write("\x1a") 
       xd = int (rcs[ind+11])
#       print "Point0",int(xd)

       if xd >= 1:
              ser.write("at+cmgl\r")  # if we have received and SMS, read it and decode it
              rct = ser.read(150)
              ind = rct.find("READ")
              print "point1:", (rct)
#              print "Point2:", int(ind)
              Phnumber =  rct[ind+8:ind+19]
              CMD = rct[ind+44:ind+54]
              print "CMD:",CMD      # we check for the actual "CMD" received
              print "PHnumber:",Phnumber #extract the incomming phone number so we know who to reply to
              ser.write("at+cmgd=1,1\r")
              DCMD = CMD[2:5]
              print DCMD
              Good = 0     # this is where we check for the help request.
              if DCMD == "hel":
                        Help = 1
              if DCMD == "Hel":
                        Help = 1
              if DCMD == "HEL":
                        Help = 1         
              if DCMD == "Cmd":  # we accept upper and lower case "CMD"
                     Good =1
              if DCMD == "CMD":
                     Good =1       
              if DCMD == "cmd":
                     Good =1
              if Good:
                     COMMAND = CMD[6:10]
                     try:
                            Action = int (COMMAND)
                     except ValueError:   # if the command  is not the 4 digits it should be we allow the error and zero it
                            print "Number Error" # this keeps the program from halting on the error
                            Action = 0
                     print "New Command:",COMMAND
                     OldMode = Mode
                     TMode =   Action/1000   # the command is 4 digits, 1240= Mode 1 for 240 minutes. Dividing by 1000 gives us the Mode
                     if TMode == 4:   # mode 4 is the status request
                            Mode = OldMode  # make sure we keep the prior mode , i.e. the unit was in mode 1 and is counting down to turn off.
                     else:
                            Mode = TMode
                            Timer = Action % 1000  #we divide by 1000 and take the remainder as the number of minutes we want to operate
                            Stime  = Minut + Timer # i.e. 1040 /1000 = 1(mode) and the remainder is 40, the minutes to operate.
                     SendFlag=1   # this flage keeps track if we have sent an sms. 
                     ser.write("\r")
                     time.sleep (1)
                     ser.write("at+csq\r")  # this grabs the signal level from the radio
                     Sig = ser.read (50)
                     ind = Sig.find("Q")
                     print (Sig)
                     SigLevel =   Sig[ind+3:ind+6]  # this is where we extract the value from the string
                     print  "Sig:", SigLevel

       print(read_temp())   #go read the temperature
       Temp = int(read_temp()) 
       seconds = int (time.time() - startime)
       print COMMAND,":",Phnumber, "Mode:", Mode, " On for:",Timer, "Minutes   Stoptime:",Stime, "HighTemp:",HighTemp
       Msg = 0
       xc = "0"
       xd = "0"
       Minut = seconds / 60
       if Mode == 1:
              if Stime > Minut:
                     remaining = Stime - Minut
                     RelayFlag =1                  #turn on the relay flag if time remains   
              else:
                     remaining =0              
                     RelayFlag =0 
       if Mode == 2:
              if Temp  < HighTemp:   #check to see if the ambient tempertature is below our high set point
                     if Stime > Minut:  # if it is,  then check the timer. turn on the relay flag if time ramains
                            remaining = Stime - Minut
                            RelayFlag =1   
                     else:
                            remaining = 0
                            RelayFlag = 0
              else:
                     Stime = Minut
                     remaining = 0
                     RelayFlag = 0 
       if Mode == 3:     # if the ambient temperature is below our high temperature set point, turn on the relay flag
              if Temp < HighTemp:                     
                    RelayFlag =1  
              else:                  
#                     Mode = 1
                     Stime = 0
                     RelayFlag =0
                     
       if TMode == 4:
              Mode = Mode  # this is a status request
                                   
       if Mode == 5:
              HighTemp = Timer  # mode 5 takes the lower 3 digits of the comand and sets our high temperature limit
                                # i.e  5055 = Mode 5 and sets our high temp limit to 55 degrees F
       if RelayFlag == 1:
              GPIO.output(Relay, GPIO.HIGH)  # this turns on the relay if the flag is set
              dret = "ON"
              sentflag=0
       else:
              GPIO.output(Relay, GPIO.LOW)        
              dret = "OFF"
              if sentflag == 0:
                     sentflag = 1
                     SendFlag = 1
       print "SendFlag:",SendFlag, ": Sentflag;",sentflag, " HelpFlag:", Help
       print Phnumber,":",Mode,":",dret,":",remaining,":",Temp,":",HighTemp,":",SigLevel
       if Help:     # if we received an "Help" request, the following gets sent
                             ser.write("at+cmgs=\"") #set the radio to send an SMS
                             ser.write(Phnumber)     #the phone number to send it to
                             ser.write("\"\r")
                             time.sleep(5)  #the actual message
                             ser.write("Mode 1: 1240= on for 4hrs\n")
                             ser.write("Mode 2: 2300 on 5hrs OR HighTemp\n")
                             ser.write("Mode 3: On UNLESS HighTemp\n" )
                             ser.write("Mode 4: Request Status\n" )
                             ser.write("Mode 5: Set HighTemp:5055 sets HighTemp to 55f")          
                             ser.write("\x1a")  # this is the command to the radio to commence the sending of the SMS
                             Help = 0
                             SendFlag=0

              
       if SendFlag:
                     if TEST == 0:   # The test flag, if set, skips this section, resulting in NO sms being sent
                             print "Sending SMS"
                             ser.write("at+cmgs=\"")
                             ser.write(Phnumber)
                             ser.write("\"\r")
                             time.sleep(5)
                             ser.write("Mode:")
                             ser.write(str(Mode))
                             ser.write( "  ")
                             ser.write("  Heater:")
                             ser.write(dret)
                             if dret == "ON":
                                    ser.write(" For ")
                                    ser.write(str(remaining))
                                    ser.write(" Minutes")                                    
                             ser.write(", Temp:")
                             ser.write(str(Temp))
                             ser.write("  HighTemp set to:")
                             ser.write(str(HighTemp))
                             ser.write(" Signal Level:")
                             ser.write(str(SigLevel))             
                             ser.write("\x1a")
                             print "SMS complete"
       SendFlag = 0
        


                       
       print Minut ,":", seconds % 60
 
       time.sleep(5)
 
 

Credits

Chuck Miller

Chuck Miller

1 project • 2 followers
Retired Engineer

Comments