Welcome! Log In Create A New Profile

Advanced

Defender Arduino Design

Posted by beads 
Defender Arduino Design
July 27, 2019 08:17PM
Hi

I recently discovered your great posts on the Mosquito Magnet Defender (my model). The Defender catches lots of mosquitoes, when it runs properly. When it failed to start this year, I gutted my Defender and replaced the board with an Arduino Mega, using three MOSFETs to control the fan, ingnitor and valve. Also added were two temp sensors and a DHT11 temp/humidity sensor. For data, I installed an OLED LCD display externally that gives great feedback on current mode, temps, run time, etc, and a micro SD card so that all the operating parameters are dumped every 1 minute during TRAPPING, and every 2 seconds during start and cool down.

It works like a champ now!

I am totally willing to share the source code and wiring; I don't have the patience to do a blog or web page, and thought you may be interested. For anyone with moderate engineering skills, the mod is very easy.

https://photos.app.goo.gl/WDych3s443LC6fN86

https://photos.app.goo.gl/JaLypzVs6Sdqek4s9

https://photos.app.goo.gl/H6SXEWRaktXsmK2YA



Edited 2 time(s). Last edit at 08/08/2019 10:42PM by beads.
Re: Defender Arduino Design
July 27, 2019 09:25PM
That looks great! Also, a lot of work! I am very interested to know what you did. I hope you are catching tons (OK, grams) of mosquitos!

It looks like your new controller is firmly attached to the combustion chamber, a far cry from my NodeMCU daughter module addition, which dangles off the old controller a few inches towards the front, away from the weather (the fan output port), plugged into and supported only by a bunch of wires going to the various inputs and outputs. And that board has another daughter (the external temperature/humidity sensor) dangling from that! Not too professional.

A few questions: What do your extra sensors do? I see you are using the thermistor, and another module is tied to the chamber heat sink fin, plus the two other sensors you mentioned. Do measure your combustion chamber? What temperature ranges are you getting? Do you know why your controller failed? Anyway, very cool.

If you want to publish your project on the wiki, let me know and I will add you as a user to the wiki. You can also sort of publish it to this forum, but that is more for discussion and announcements.
Re: Defender Arduino Design
July 28, 2019 10:28PM
[posted from email]
I submitted a request for an account, but beyond the "click to get registered" email, nothing has come in. (see below)

To answer the quick questions...the recorded data is fantastic at troubleshooting- that's how I found out the thermistor was bad and therefore completely skipped it. You are correct- I have one temp sensor on the hot section, and an identical one exposed to external air out of the bottom below the valve. A third temp sensor DHT11 (not a very good sensor) is ported through the hole where the old power connection used to be. One of the other cool things is the RTC (real time clock))- the next step is to program it to only come on during prime catching hours to save propane. I even intend to calculate sunrise/sunset based on Latitude so the on/off times adjust as the season progresses. I attached a couple day run. The a2Tempo doesn't get read during ignition; it looks only at the delta temp (dTemp) of the sensor on the heating element. Once in trapping- it looks for the delta temp between ambient and the hot section.

The OLED display is great; the yellow top line is legible pretty far away, and tells me what mode it is in. I ran out of propane recently, and it worked exactly as it was supposed to- the fan keeps running for a few hours until the little blood suckers are dried out. I have a small backyard, and have noticed that as the years pass, fewer and fewer mosquitoes are present. They really are weak fliers.

I just want to share my work- the Defender has made our backyard usable again, only when we get it to light off!



Edited 2 time(s). Last edit at 08/11/2019 07:36PM by beads.
Re: Defender Arduino Design
July 30, 2019 06:00PM
That's pretty impressive! I don't see why that can't work with a liberty too.
I'm on the list.

Arduino has no OS, so it's purely embedded? What lang is your source?
I have no experience with them.

Thanks!
Re: Defender Arduino Design
July 31, 2019 12:28AM
The Arduino runs on a version of C++; the IDE can be downloaded to a laptop or PC, then when the code is written and compiled, it is "squirted" to the Arduino Mega via the USB. That big blue USB cable hanging out serves two purposes: it allows me to update the code (this was definitely a work in progress), and there is also a serial mode that "prints" variables and states to the laptop to improve trouble shooting.

The real Arduino benefit is the real time clock (RTC). I’ve been checking the trap frequently to see when mosquitoes show up. In the heat of the summer, virtually nothing gets caught between 11:00 PM and 3:30 PM. Does anyone know of a definitive source for mosquito biting times? My thought is also to use the ambient temp to cause the magnet to switch on and off; logic something like "if after 3:30 PM AND less than 95 degrees F then start ignition" then shut down after 11:00PM or roughly those numbers.

I was too busy building the thing to take nice pictures of the wiring. I plan on building a second one, since I just received two used Defenders that I bought on EBay; I’ll do a better job on the next one. The SD card is a pain to access since I put it on the bottom; the SD card mount is 3D printed (my 5+ year old Makerbot 2 still works!). I can’t say enough good things about having that SD card record data every minute while trapping.
Is there interest enough for me to post the parts list (mostly Amazon) and provide code and diagrams?


Here are more pictures:
https://photos.app.goo.gl/KJra9vfPqm7oeaVS9 SD card and switch

https://photos.app.goo.gl/uHx2146TDzmPWYns6 Before mounting stuff
https://photos.app.goo.gl/at5tyeBmjqChUt1x8 igniter glowing using the MOSFET
https://photos.app.goo.gl/BBRadH7zj28ozuxo7 The blue DHT11 sensors stink! Slow, and poor accuracy. The humidity part works well, though

The seven year old Defender catches a lot of Skeeters now!
MAGNET_7-27-2019-post.csv
Re: Defender Arduino Design
July 31, 2019 01:03AM
Dang, I didn't think the SD data file attached to my last post, so I deleted references to it. In the attached iteration, the lightoff delta temp "dTemp" is set to 11.1 deg F (I added the decimal when I was screwing with the crummy DHT11 sensors that only output integers.) The loop# in trapping has since been updated; it indexes by one now; the Arduino now only sends the data to the SD card every minute, since the files were getting unwieldy. However, the "TRAPPING" loop still occurs about every 2.8 seconds, which explains the large gaps in the loop# value. I had to add a delay to allow the temp sensor time to read.

In the file, dTemp- the temp difference between the sensor on the hot section fins and the near ambient sensor- reaches 11.1 degrees F, the code decides that is light off and moves from "IGNITION" to TRAPPING." The current dTemp setting is 20.1 degs. In the Ignition cycle, "elapsed" is in seconds.

The code is below (-hopefully it works). I'm an aerospace engineer, not a coder by trade, so please have mercy!

//Mosquito Magnet Defender
//Version 11
#include <util/delay.h>
#include <Wire.h>
#include <SD.h>
#include <SPI.h>
#include <dht.h>
#include <OneWire.h> 
#include <DallasTemperature.h>
//  Temp sensor driver
dht DHT; 
#define amb_temp 8// Pin ambient temp sensor is connected to
#define igPin 9
#define fanPin 10
#define valvePin 11
#define sd_card 53
#define Temperature_ONE_WIRE_BUS 2 
#include "SSD1306AsciiAvrI2c.h"//OLED Display driver and address
#define OLED_ADDRESS 0x3C //set I2c Address, OLED specific
SSD1306AsciiAvrI2c oled;
OneWire oneWire(2); // DS18B20 temperaure sensors
DallasTemperature sensors(&oneWire);

  float chk; 
  int ignit =0;
  float start_time = 345.1;// total igiition cycle until timeout 
  float lightoff = 20.1;// delta T (deg F) for ignition
  float temp = 0;
  float dTemp = 0;
  float aTemp; float a2Temp;
  unsigned long readsec;
  unsigned long initTime;
  int elapsed;
  int x = 0; int y = 0;
  int sec = 0;
  byte iMinute = 0;
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  String stat = "IINITIALIZE"; String stat2 = "unassigned";

File myFile;

#define DS3231_I2C_ADDRESS 0x68 // Real time clock 
byte decToBcd(byte val){
  return( (val/10*16) + (val%10) );}
byte bcdToDec(byte val){
  return( (val/16*10) + (val%16) );}


void setup(){
  Serial.begin(19200);
  initTime = millis()/1000;
  sensors.begin(); 
  get_temps();
  
  pinMode(sd_card, OUTPUT); // SD card init
  Serial.print("Initializing SD card...");
  if (!SD.begin(53)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  myFile = SD.open("Magnet.txt", FILE_WRITE);
  // if the file opened, write to it:
  if (myFile) {
    myFile.println("initializing SD card,  Mosquito Magnet  ");
    myFile.println("loop#,dayofmonth,month,year,Hour,Min,sec,Loop#,stat,stat2,elapsed,temp,aTemp,dTemp,a2Temp,");
    myFile.close();
  }

  oled.begin(&Adafruit128x64, OLED_ADDRESS); //OLED Display init
  oled.setFont(Adafruit5x7);
  uint32_t m = micros();
  oled.clear();
    
  refresh_oled(); //Show initialize screen to check temp sensors
  delay(6000);
  
  pinMode(fanPin, OUTPUT);pinMode(igPin, OUTPUT);pinMode(valvePin, OUTPUT);
  analogWrite(fanPin, 400);// Set fan to low speed
  digitalWrite(igPin, LOW);// igniters off until called
  digitalWrite(valvePin, HIGH);//propane on
  
  ignite_cycle();
        Serial.print("up top ignit ");Serial.println(ignit);
      if (ignit == 1){
        stat2 = "Ignition successful";
        Serial.println(stat2); 
        } 
      else {
        stat2 = "Ignition time out";
        Serial.println(stat2); 
        cooldown(); 
        }
    
analogWrite(fanPin, 1000);// Set fan to high speed
initTime = millis()/1000;// reset seconds after ignition
}


void loop(){
       stat = "TRAPPING";
       lightoff = dTemp - 0.5;//provides margin from ambient
       
  while (dTemp >= lightoff){    //    temp delta above ambient that shows ignition continues         

       x++; Serial.println(x); //counts loops
       sec = millis()/1000;// provides run time to display
       elapsed = (sec - initTime); // provides current run time
       
       get_temps();
       
       iMinute = minute;
       readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
       
          Serial.print("Temp = ");  Serial.print(temp); Serial.print(" Amb Temp = ");  Serial.print(aTemp);
          Serial.print(" dTemp = ");  Serial.print(dTemp);Serial.print("   Humidity = ");  Serial.println(DHT.humidity);
  
          Serial.print(hour, DEC); Serial.print(":"); Serial.print(minute, DEC); Serial.print(":"); Serial.print(second, DEC);Serial.println(" ");
          Serial.print(month, DEC);Serial.print("/"); Serial.print(dayOfMonth, DEC);Serial.print("/"); Serial.print(year, DEC);Serial.println();

          if (iMinute != minute){
                  y++;
                  myFile = SD.open("Magnet.txt", FILE_WRITE);  
                  myFile.print(y); myFile.print(","); myFile.print(dayOfMonth); myFile.print(","); myFile.print(month); myFile.print(",");myFile.print(year);
                  myFile.print(","); myFile.print(hour); myFile.print(","); myFile.print(minute); myFile.print(","); myFile.print(second); myFile.print(",");
                  myFile.print(stat); myFile.print(","); myFile.print(stat2); myFile.print(","); myFile.print(elapsed); myFile.print(",");   
                  myFile.print(temp); myFile.print(","); myFile.print(aTemp); myFile.print(","); myFile.print(dTemp); myFile.print(",");myFile.print(DHT.humidity);
                  myFile.println(",");
                  myFile.close(); 
          }   
  
      refresh_oled();
   }
   x = 0;     
   cooldown();
}

void ignite_cycle(){
  myFile = SD.open("Magnet.txt", FILE_WRITE);
  myFile.println("elapsed,temp,aTemp,dTemp,a2Temp,stat,stat2");myFile.close();
  stat = "IGNITION";
  digitalWrite(igPin,HIGH); // start igniter
  Serial.println("inside ignite_cycle"); 
  
  while (elapsed < start_time && dTemp < lightoff) {
    x++;
    readsec = millis()/1000;
    elapsed = (readsec - initTime); // provides run time
    get_temps();
    
    Serial.print("dTemp "); Serial.println(dTemp); Serial.print("temp "); Serial.println(temp); 
    Serial.print("aTemp "); Serial.println(aTemp); Serial.print("time "); Serial.println(elapsed); 

    myFile = SD.open("Magnet.txt", FILE_WRITE);
    myFile.print(x); myFile.print(",");myFile.print(elapsed); myFile.print(","); myFile.print(temp); myFile.print(","); myFile.print(aTemp); myFile.print(",");myFile.print(dTemp);
    myFile.print(","); myFile.print(a2Temp); myFile.print(","); myFile.print(stat); myFile.print(","); myFile.println(stat2);
    myFile.close(); 
    
      oled.clear(); oled.set2X();
      oled.println(stat); oled.set1X();oled.println();
      oled.print(temp); oled.print("    ");oled.println(dTemp);
      oled.print("temp"); oled.println("     dTemp"); oled.println();
      oled.print(" Ignition time: "); oled.println(elapsed); oled.println();
    
  }

  digitalWrite(igPin,LOW); // stop igniter
  if (elapsed <= start_time){ignit = 1; // 
       stat2 = "Good Ignition"; Serial.println(stat2);oled.println(stat2); delay(1000);}
  else {ignit = 2;
  stat2 = "No Ignition"; Serial.println(stat2);oled.println(stat2);}
}

// Real time clock setup
 void readDS3231time(byte *second,byte *minute,byte *hour,
  byte *dayOfWeek,byte *dayOfMonth,byte *month,byte *year){
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set DS3231 register pointer to 00h
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}

void refresh_oled(){ //Push data to the OLED display
        oled.clear(); oled.set2X(); oled.println(stat);oled.set1X();
        oled.print(temp); oled.print("  ");oled.print(aTemp);oled.print("  ");oled.println(DHT.humidity);
        oled.print(" temp"); oled.println("   ambt   humid.");  oled.println();
        oled.print(hour, DEC); oled.print(":");
        oled.print(minute, DEC); oled.print(":");
        oled.print(second, DEC);oled.println(" ");
        oled.print("Loop#");oled.print(x);oled.print(" Elapse:");oled.println(elapsed);
        oled.println(stat2);oled.print("Mosquito Rev7");
}

void cooldown(){
      stat = "COOLDOWN ";
      digitalWrite(valvePin, LOW);//propane off
      digitalWrite(igPin, LOW);//be sure ignition is off\
      analogWrite(fanPin, 1000);// Set fan to high speed
      Serial.print(stat); Serial.println(stat2);Serial.print("dTemp "); Serial.println(dTemp); Serial.print("temp "); Serial.print(temp); Serial.print("  a2Temp"); Serial.println(a2Temp); 
      x = 1;
      while (x < 900){// 60 = 2 minutes;  cool down 
         x++; 
           Serial.print("loop ");  Serial.print(x); Serial.print("  ");
           Serial.print(stat); Serial.println(stat2);Serial.print("  temp:"); Serial.print(temp); Serial.print(" aTemp:"); Serial.print(aTemp); Serial.print("  a2Temp:"); Serial.println(a2Temp); 
           get_temps();

         readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
 
              myFile = SD.open("Magnet.txt", FILE_WRITE);
              myFile.print(x); myFile.print(","); myFile.print(dayOfMonth); myFile.print(","); myFile.print(month); myFile.print(",");myFile.print(year);
              myFile.print(","); myFile.print(hour); myFile.print(","); myFile.print(minute); myFile.print(","); myFile.print(second); myFile.print(",");
              myFile.print(stat); myFile.print(","); myFile.print(stat2); myFile.print(","); myFile.print(elapsed); myFile.print(",");   
              myFile.print(temp); myFile.print(","); myFile.print(aTemp); myFile.print(","); myFile.print(dTemp); myFile.print(",");myFile.print(a2Temp);
              myFile.println(",");
              myFile.close(); 
         
         refresh_oled();
      }
      analogWrite(fanPin, LOW);// turn fan off
      stat = "HALT";
      Serial.println(stat);
      refresh_oled();
      while(1); //forever loop
}

void get_temps(){
  sensors.requestTemperatures(); 
  temp = sensors.getTempFByIndex(1);// Hot location initial temp
  aTemp = sensors.getTempFByIndex(0);// Ambient location initial temp
  dTemp = temp - aTemp;
  chk = DHT.read11(amb_temp);
  a2Temp = DHT.temperature*1.8+32;
  delay(2000);
}



Edited 1 time(s). Last edit at 08/11/2019 07:38PM by beads.
Re: Defender Arduino Design
July 31, 2019 11:46PM
This is GREAT stuff! :-)

I'd like to build one. If you have a chance to put together the amazon parts list, please post. :-)

So you've got serial out for the display, a file for the data storage. I didn't see anything for input. So this just fires up and runs until the flame goes out?

Are you using a separate power supply or did you hack the stock one?

mosfet for gas valve is driven off arduino pin 11, which you set hi or lo and which in turn gates 12v on or off to the valve. Am I following this properly?

The diagnostic capability is great with this setup. How much memory do you have to work with? Do you know how much you have free beyond what you code is using?

Questions, questions. Inquiring minds want to know! ;-) Thanks!
Re: Defender Arduino Design
August 01, 2019 01:04AM
This forum proved to me that the Mosquito Magnet was one of those great ideas that people really want to work better...I wonder if they are monitoring these threads! The physical design is really good, too bad they went super cheap for the control system.

To answer the questions: There are three temp sensors. Two are really nice temp DS18B20s, one mounted on the hot section, the other in a hole drilled through the bottom of the case near the valve to provide somewhat ambient temps. My initial code read the thermistor, but now I know it doesn't work on the old unit, and I used super tough two part epoxy the last time it was replaced, so it stays! Another input is the RTC, a DS3221. I bought a 10A 12V power supply, and used a standard 5.5m jack. I discovered that I needed a stress relief loop- without it, it came unplugged since it was vertical.

The MOSFETS are the key- super cheap and reliable. We can thank the vaping crowd for the great improvement in cost and performance of these devices. The Arduino Mega is powered directly from the 12V power supply, using a standard 5.5mm plug

The build uses mostly jumpers, with small strips of Gorilla tape to keep them from pulling apart or off the board. I put a weather proof switch on the bottom. The original weather proof switch is eventually going to be used to turn the OLED off when not needed; I also plan on adding a dual color LED to indicate general status that is easily viewable from a distance. Total parts cost is about $45, though I replaced the igniter as well, which added $25.

The code posted previously is just a simple turn it on and let it run until the propane runs out version. I drafted the "final" version today which will cause the magnet to automatically turn on and off at specified times using the RTC. It is a trickier problem than one might think. Distinguishing between shutdown for time and loss of propane prevents the basic structure of the original While loop to be used.

A full parts list:
Good temp sensors
temp/humidity sensor
power supply
Arduino Mega
Oled display
Real time clock
Micro SD card reader
Big MOSFETS
Jumpers


Re: Defender Arduino Design
August 01, 2019 11:17AM
I'm sure I could figure it out, but do you have some sort of schematic? I don't need a diagram, only what goes from where to where.

A couple of questions...

Setup of the RTC? I don't see that in your code. Is that done externally for now?
Timing on the temp reads. Have you modded your code for the better sensors?

Also, your scheduling concept is good. In my experience, they tend to bite most at dawn and dusk, this will save propane, but the pheromone attractant will still vaporize over time, so that's a consideration.

Thanks!
Re: Defender Arduino Design
August 01, 2019 07:05PM
I read through your code and other posts and am happy to hear that your Defender is catching mosquitos. I have a few questions and comments.

First, did you replace the thermistor itself before? You wrote that you epoxied the assembly to the case. I wonder, however, to what extent does that epoxy conduct heat? The thermistor bracket is supposed to be thermally isolated from the case in order to conduct the high combustion temperature to the outside where the thermistor can register ~120°C. Using a metal screw, not using the insulating bushing, and/or attaching a heat conducting putty will "short" the thermal circuit. The combustion chamber outside temperature is quite a bit lower than inside, and takes much longer to respond to combustion changes. This may be the reason the thermistor no longer was effective. In my unit, it is very sensitive and quite effective. It can measure the temperature rise from the igniter alone in the absence of propane, which checks the igniter. Although it looks like a lot of steps, it is not that difficult to drill out the epoxy, free the assembly, drill out the old nylon bolt, clean the threads, and add a new nylon 8-32x1/2 bolt. Or maybe not...

My unsealed, unprotected daughter board add-on has suffered from issues of weatherproofing, moisture, undesired conduction, and corrosion. I cannot recommend my approach of attaching a daughter board to the existing controller until these issues are addressed. You may face the same issues with yours, which has an even larger exposure.

Suggestion: instead of an SD card, could you use MQTT? Does your Arduino have WiFi or MQTT capabilities? If not, could you add a module? This would solve the large log problem, since you could save the messages on your computer instead of the SD card using an MQTT client (e.g., mqtt-spy). I found it very convenient to be able to check the status and remote control the unit from anywhere in the world using the smart phone. It has been a real game changer. For example:
Temp=129.9C (-1.8) at 5:58325 F=1 I=0 G=1 S=1 E=0 T=62.5C H=1.8% M=11248 (198/1013:4573) R=45~140 B=1.0 V=3.1
Reading your Version 11 software, on power up, the unit executes the setup routine, which turns on the gas and fan low speed to commence ignition. The original Defender had an annoying 3 minute fan only phase to cool the unit and exhaust any residual propane. I concluded this was done as a safety measure, and to check the operation of the thermistor temperature sensor. These traps are so frustrating because of their multiple safety checks that, when they fail, prevent the operation of the trap. This plus the fact that the system does not include really any error reporting, so there was no way to tell what is happening, requiring costly and time consuming return for repair. No one can afford the downtime. I believe that more status and error checking is helpful in the interest of safety and troubleshooting. But the most important thing is that, in one way or another, if the trap has failed, and it may be unsafe or non-optimum to run it anyway without correcting the underlying problem. My trap has suffered from a lot of underlying problems, including lately. See the blog. In my case, I didn't want to worry about creating a potentially dangerous situation, so I included as many or more checks as in the original, at least as far as I could determine. For example, I start the igniter before the propane, to detect correct igniter operation. The Liberty has a separate circuit and amplifier to measure the igniter current, but that is not available on the Defender.

I missed seeing your On/Off switch in Version 11. I use the switch to cool down the trap before moving it, rather than unplugging the power. Mosquito Magnet specifically warns against moving the trap hot (but I don't know why). With the trap on the lawn, I had to move it daily to avoid killing the grass. I confess to moving the operating trap may times. My method is to grab and lift the tank with one hand, then the pole with the other, and move a few feet gently. On the other hand, I have gone through a few igniters, so this may not be a good idea, and use of the On/Off switch is recommended.

Your example has really inspired me to reconsider publishing details of the IOT controller add-on. I have been reluctant to do so out of concern for public safety, as the propane trap is a potentially dangerous device. But DIY seems pretty alive and well, so maybe I should just do it. But before doing so, I feel I should come up with a real design mechanically, including mounting, strain relief, and protection from the elements. However, this will have to wait, since I have only one Defender, and it is very busy now.



Edited 1 time(s). Last edit at 08/01/2019 07:11PM by dev.
Re: Defender Arduino Design
August 01, 2019 11:23PM
Dev has a lot more experience with the Defender/Liberty than I do, that's for sure. I understand the safety issues for general consumers, but DIYers have a *reasonable* appreciation for risk mitigation. I personally spent years as a Navy Test Pilot and Test Pilot Instructor- they beat ORM (Operational Risk Management) into our thick pilot skulls repeatedly! That said- the actual flame from the magnets is pretty paltry, so I think the only significant danger is a relatively large leak or valve stuck open without any ignition source, and then "suddenly" gets lit.

The propane flow is in my opinion too slow to be a hazard from a location more than a couple feet away, unless in a tight and enclosed space. Definitely use at your own risk!

I thought about replacing the thermistor- but the Arduino seems to be doing a great job with the two main temp sensors, so as long as it is not broke...

We have had a couple strong thunderstorms blow through, and so far the Defender has held up fine. Next season may be a different story, though.

The wireless capability is really cool, better than having to wait to shut down to read all the stored data. Does the MQTT data get recorded The OLED display does show pretty much everything needed to understand how things are going in the code and burner. Honestly, future iterations may not include the SD card if everything continues work.

To answer previous questions: the Real Time Clock (RTC), the DS3231, is set up in a smaller separate code- it only needs to run once unless the battery fails. The time/date has to be typed in right below "serial.begin." The second half of the code is just to read and display the time to check that it "took."



#include <Wire.h>
#define DS3231_I2C_ADDRESS 0x68

// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)

{

  return( (val/16*10) + (val%16) );
}

void setup()
{
  Wire.begin();
  Serial.begin(19200);
//DS3231 seconds, minutes, hours, day, date, month, year
setDS3231time(50,52,19,1,24,6,19);
}
void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte
dayOfMonth, byte month, byte year)
{
  // sets time and date data to DS3231
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set next input to start at the seconds register
  Wire.write(decToBcd(second)); // set seconds
  Wire.write(decToBcd(minute)); // set minutes
  Wire.write(decToBcd(hour)); // set hours
  Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
  Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
  Wire.write(decToBcd(month)); // set month
  Wire.write(decToBcd(year)); // set year (0 to 99)
  Wire.endTransmission();
}
void readDS3231time(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{

  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set DS3231 register pointer to 00h
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}

void displayTime()

{

  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  // retrieve data from DS3231
  readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,
  &year);
  // send it to the serial monitor
  Serial.print(hour, DEC);  Serial.print(":");
  Serial.print(minute, DEC);  Serial.print(":");
  Serial.print(second, DEC);  Serial.print(" ");
  Serial.print(month, DEC);  Serial.print("/");
  Serial.print(dayOfMonth, DEC);  Serial.print("/");
  Serial.print(year, DEC);  Serial.println();
  }

void loop()

{
  displayTime(); // display the real-time clock data on the Serial Monitor,
  delay(1000); // every second
}




The two "new" temp sensors are already coded and called by "sensors.getTempFByIndex(0);" or "sensors.getTempFByIndex(1);" There are two libraries that need to be downloaded to get the temp sensors to work:
#include <OneWire.h> Located here

#include <DallasTemperature.h>
located here

The current code (the one posted) use 10% of program memory and 22% of dynamic memory for variables. That 's why I went with the Mega, though all the peripheries make it the right choice as well.

As for biters- I hardly see any in the morning in the trap about an hour after sunrise after operating all night. The trap stays empty until about 1600, then activity starts picking up. I recently bought a micro Doppler radar chip, with the thought it might be a way to very roughly get an idea of activity in the trap. It won't count mosquitoes individually- but if they are flying around I'm hoping they will show up on radar and provide a rough idea of activity levels. Otherwise, mosquitoes have a very distinct acoustic signature that could be monitored if the signal to noise ratio is manageable. My goal is to track catches so that the operating time can be precisely tuned.

This project is a time sink, but our backyard is once again livable.
Re: Defender Arduino Design
August 02, 2019 10:21AM
This is getting better and better! :-)
Re: Defender Arduino Design
August 02, 2019 02:11PM
Wow, great message. That Doppler Motion Sensor is very exciting, and I got lost looking at that site with all its gadgets. While we're on the subject, what I really want is a 0-1 psi propane pressure and flow sensor (that's 2 sensors). Any ideas?

"I understand the safety issues for general consumers, but DIYers have a *reasonable* appreciation for risk mitigation."

You know, I wonder. In my case I'm afraid my "mosquito phobia" may have led to some questionable decisions on my part. Not too many have had your high level of training. It may be hard to imagine less responsible people like me, but we are out here. This brings to mind a coworker who enjoyed doing stuff like "strapping (various things) up for higher power." The highlight was him taking an old dorm refrigerator sized transformer hauled into the back yard near a utility pole, somehow attaching heavy wires up onto the raw 220 volt power line, connecting them to the transformer, then watching the transformer buzz, overheat, and catch fire. The show wasn't as spectacular as it had been billed, but it did make an impression on me.

" ... so I think the only significant danger is a relatively large leak or valve stuck open without any ignition source, and then "suddenly" gets lit."

I think that's it. The scenario of an intermittent or marginal igniter and/or fan, a somewhat leaky valve, an aborted start cycle caused by a brief power interruption, then a restart, and boom! Actually, I remember the original Defender making an muffled explosive "bang" upon ignition for about a season after I had replaced the something or other (the nozzle?). Fortunately, there was no shrapnel: my combustion chamber held together, again and again, although I was concerned. I don't think the original designers would have permitted the trap to make these sounds, yet there they were... The original Liberty had an awful lot of error checking that was not in the Defender. I discussed some of that in the wiki. With small children, I wanted to completely eliminate that internal explosion.

"Does the MQTT data get recorded?"

Not always. I have to run an MQTT client to do that. I use MQTT Snooper on the phone, and mqtt-spy, an open source java application on the PC. (You need java on your machine. Download the pre-compiled .jar file with dependencies.) The PC is easier to use, and the app's log files can auto-rotate, and/or get quite large. The V3.1 software transmits 19 channels. I use a display application to parse and graph the log files. It can also capture the MQTT signal directly for a real time graphing display. I am recording now because I have an intermittent underlying anomaly (reduced combustion temperature) that I believe affects operation. The software stops the trap when such an anomaly occurs. I expect the trap to have problems today, so I am recording now, and have been for the past week or so. You can monitor the signal yourself using an MQTT client: the current server is the free broker.hivemq.com, and the topic is MMD/esp11817981 or another number based on which NodeMCU board is in service at the time. There may be several boards operating simultaneously, so pick the one with the realistic looking temperatures and humidity. Just now:
Temp=124.3C (0) at 5:37327 F=1 I=0 G=1 S=1 E=0 T=54.1C H=6.3% M=11288 (223/1012:5320) R=45~140 B=1.0 V=3.1
The wiki has an explanation of the various fields. The server is a free demonstration device, which has service interruptions from time to time, which is perfect for testing software error handling (although I missed a failure event because of this). I guess I didn't want to have to stand around a problematic or even perfectly working trap with who knows many blood-thirsty mosquitos hovering within just a few feet. The software implements 8 commands via MQTT, plus several parameters (e.g., network, server, topic, etc.) via the trap's combination status/configuration web page.

I operate the Defender continuously (as long as it will run). I don't catch very much during the heat of the day, but those I do catch I appreciate. Day time flying mosquitos, while not so many here, are definitely up to no good, and I don't want them to establish a foothold. This way, I can keep them at bay, and enjoy the daytime sans mosquitos. Also, I don't want to wear out the igniter, which has a limited number of cycles before it fails. Also, the cost of propane at about $2.15 gallon, or $9 for 4.2 gallons in a 20# tank is not that costly. I have extra tanks for replacement. I weigh the tanks with a luggage scale to judge when to exchange tanks instead of letting the trap run dry. Finally, the attractant, which I buy in 10ml vials, evaporates whether the trap is running or not. So I am on site every three weeks or so, regardless.

I am jealous of your low Arduino memory utilization. My software is completely constricted by memory. One of the MQTT reported parameters is the free memory (M=11288 above) in bytes. If it gets too low, memory allocation fails, crashing the system, which reboots. On the other hand, the main control logic, networking, MQTT communication, web server, and configuration modules all fit and work, so I'm happy. And it is quick to update a module. I was considering adding over-the-air updating, but have not gotten around to that yet. Swapping the NodeMCU out is easy enough: basket & cover off (no screws), power down, unplug the old module, plug in the new one, power up, cover on, basket in. And the less familiar lua language is pretty convenient for this application. It is event driven, so you use timers instead of delays for timing or periodic checks, and event callbacks for handling network traffic or other interrupts. All routines must execute quickly and return to the OS without delay. It's a little like handling Windows API messages, there is no main loop. And the NodeMCU cost $4, so it is easy to have several of them for experimentation, backup, etc.

But still I could add more functionality. I would like to weigh the tank, report gas pressure and flow, add an outside temperature and humidity sensor, and, for fun, your idea for a Doppler motion or mosquito tone idea detector. I could graph this to see what's happening when. I might have to switch to the 100% compiled lua executable method (which supports vastly expanded program and data memory) to accommodate all this extra stuff!



Edited 1 time(s). Last edit at 08/02/2019 03:41PM by dev.
Re: Defender Arduino Design
August 04, 2019 07:22PM
It is worth addressing the risk of explosion, since that is obviously a concern. The likelihood of a catastrophic failure of the mosquito magnet burner section in worst case conditions is virtually zero, based on some simple math. Also, given how prone the original sensors and control system are to failures, the company could not produce a product that had any measurable risk of explosion. There are videos of guys igniting the magnet with a torch lighter through the vacant igniter hole (skip to 5:00).

The entire volume of the Defender burn section, including the catalytic converter, is about 38 cubic inches. The output “nozzle” is nowhere near choked (flow will not go supersonic under pressure), so the risk of a failure of the burner section even with the perfect ratio of propane to gas is almost zero. If there are no fractures or corrosion through the sidewalls, there is no threat other than a pop. I definitely had one “pop” during development when I powered down the 12V transformer but left the USB cable connected and powering the Arduino. The pop happened when the Magnet was repowered, but it was nothing near what I would consider a threat to the heavy burner section.

The stoichiometric (perfect) air/fuel ratio for air to propane is 23.83:1. So, if the ratio was perfect, and therefore the maximum “explosive” capability, there would be a grand total of 1.54 cubic inches of propane at one ATM in the entire Defender hot section. One cubic foot at the ideal air/fuel ratio generates 2590 BTUs, so our Mosquito Magnets can, in absolutely perfect conditions, generate a measly 28 BTUs. That’s only 8.2 Wh (0.082 KWh). My guess is that the pop, which I have heard and seen with a late light off, is actually close to the “worst case” scenario, not a small fizzle or close call which was lucky to be small. The burner section metal shell is very robust, I think more to provide thermal “inertia” than protection for a bad light off, though it does just that.

Upon further review, the Doppler sensor is tuned for long distances (shortest is about 5 meters), but there is a microwave sensor that may also do the trick. Its lower frequency and longer wavelength may be too large to see the beating wings, but it can’t hurt to try.

The Defender ran great the past five days; I checked the trap often and cleaned it out a couple times. The last cleanup I had 41 mosquitoes in less than 3 days, that’s decent for me. I’m not getting bit in the backyard, so that’s something!

The next post will *hopefully* have the code for the real time clock so the Magnet automatically comes on and off based on the time of day. The first test worked about halfway: the OLED display froze after the good ignition, so something is amiss. Also, the wiring info to post is coming together, so it would be easier to duplicate and improve on the Mega if desired and someone wants to take the risk!


A couple images of the data from the last run. The crummy DHT11 temp data (a2Temp) is all over the place, that’s why it had to be replaced. Of note- the cool down (and ignition) data is recorded 30 times more frequently than the trapping data, so the charts are exact





Edited 1 time(s). Last edit at 08/04/2019 11:38PM by beads.
Re: Defender Arduino Design
August 05, 2019 09:56AM
Great post! I feel much better already (although you can't believe everything you read on the internet). There is then the evidence of all the safety features in the Liberty and Defender. These features malfunctioning may be a major reason these machines have failed in large numbers worldwide. Perhaps the designers were being overly cautious, or they were guarding against some other scenario entirely, which would involve much larger space, e.g., a closed garage. How else to explain the ultra-annoying initial 3 minute cool down cycle upon power up? Perhaps they didn't want some "pop" to ignite some larger mixture? Something to think about.

Congratulations on your catches. Your mosquitoes seem to be under control, as are mine (for now). My machine is so unreliable for fundamental reasons, it is a nerve wracking process, but so far, it is working.

I use the word nozzle that I got from the catalog listing: "15045WDA 1.50 GALLON 45 DEGREE WDA HOLLOW NOZZLE - BRASS WITH STAINLESS STEEL ORIFICE AND DISTRIBUTOR WITH STRAINER" What is the correct term?

I wonder why the DHT11 is so bad for you. I thought it had decent specs.

So the microwave detector instead of the dopplar. Keep us posted.
Also, any ideas about a CO2 and CO combined or separate sensor. It would be good to measure the exit temp, humidity, and those gases.
Re: Defender Arduino Design
August 07, 2019 09:29PM
Woohoo!

First things first- the new code seems to be working like a champ. My Computer Science major son got on me for not using more methods and streamlining the code, so version 12 is a much better piece of code overall. The reason the OLED “froze” last try was that I completely forgot to include that new method inside the main loop; it worked for IGNITION and SHUTDOWN, but not TRAPPING. Speaking of which, there are two new modes in V12 with the Real Time Clock (RTC) :

SLEEPING- the time is outside the selected hours for propane to be on. The fan continues to run at 80% or so, because the attractant by itself is still possibly catching new biters, and the ones already in the trap need to be dried out. This is essentially the previous cooldown mode, without the HALT command at the end.

SHUTDOWN- formerly COOLDOWN; this mode is only run once when propane is gone or sensors fail, and it would have been confusing to keep the old name because theoretically, there could be a dozens of “cooldowns” for each tank. At the end of four hours, the while(1) command is an infinite loop that freezes the program there.

I created a photo album with the pictures taken to this point. The design is still a complete rat’s nest. Since it works so well, there’s no motivation to make it better.

PHOTOS

Below is the list of components and the Arduino Mega pins used. Using the 12v DC power supply, the main components (fan, ignition, valve) are connected to VCC via a wirenut, and ground through the MOSFETs. The three MOSFETs all have a main ground connector, in addition to sharing the ground with the Arduino (not sure if the Arduino ground is really necessary, but was easy and it works).

Here’s the list (see previous post for Amazon links); I tried to include the wire color in the description to help match with the photos, but don't bank on it. The component pins are listed in the order that they are on the cards

RTC (Clock) Wire_color Mega_Pin#
SCL WHT 21
SDA GRY 20
VCC PRP 3.3 VCC
GRD BLK GND (any)

SD CARD Wire_color Mega_Pin#
CS PRP 53
SCK BLU 52
MOSI GRN 51
MISO YLW 50
VCC RED 5.0 VCC
GRD BRN GND (any)

OLED Display Wire_color Mega_Pin#
SDA GRN 20
SCL BLU 21
GRD BLK GRD (any)
VCC RED 3.3 VCC

18B20 Temp x2 Wire_color Mega_Pin#
VCC PRP 5.0 VCC
OUT BLU 2
GRD GRY GRD (any)

DHT11 temp Wire_color Mega_Pin#
VCC PRP 5.0 VCC
OUT WHT 8
GRD GRY GRD (any)

MOSFETs
Igniter- Mega pin 9
Fan- Mega pin 10
Propane Valve- Mega pin 11

Note: the Mega uses the leftmost pin, the Gate. The center pin on the MOSFET is the Drain and goes to the devices (fan, valve, and igniter), the right pin is the Source and goes to the main ground in secured by the wirenut, and I also ran it to the Mega ground.

I’ll post the output from the latest run after it has a couple days under its belt. After a couple hours last night, there were 6-8 biters still flying in the trap. We need to figure out a way to count these buggers! The code will be posted separately after this.



Edited 1 time(s). Last edit at 08/17/2019 12:45PM by beads.
Re: Defender Arduino Design
August 08, 2019 01:03AM
OK- here's the latest code. The "VOID Loop()" is now really small, since all the data output and sensor reads are in separate methods.

The first IF statement in the main loop identifies the SLEEPING mode; when the propane valve is closed and only the fan runs. The code as-is is set to go to sleep between 4:00 AM and 3:00 PM. The first time the hour is outside the designated sleep time (3:00 PM), the Boolean variable "start" should be false, which then triggers the Ignite_cycle method. If there is a good light off (cross my fingers, but it has been 100%), then it runs TRAPPING mode until the stop time at 4:00 AM.

This version of the code uses 21% of dynamic memory (1725 bytes used), and 9% of program storage space (25.2 kB). The OLED display shut off isn't added- the MTBF (Mean time between failure) of the display is way higher than I thought. The display flickers every 2.8 seconds or so when it is refreshed, which is the visual indication that it is running the loop, so the external LED isn't really necessary. There are tons of remaining IO ports on the Mega to add any number of devices- including (hopefully) some way to measure trapped mosquitoes.

One thing I discovered during bench tests: the igniter MOSFET got very warm at the end of three minutes- too hot to touch. I more than doubled the size of its aluminum heat sink, but am now considering adding a new temp sensor just for the MOSFET. Because the temp sensors all use the same I/O port, it is very easy to do. When not igniting, the additional sensor would become a case temperature sensor.

Another thing I discovered: the burner temp directly correlates to fan speed. I goofed on V11 and thought the PWM (Pulse Width Modulation) for analog and digital outputs were the same range; in reality, analog pins are 8 bit (0 - 255), while digital pins are 10 bit (0 - 1023). I got amazingly lucky in V11 because if values are greater than 255 in analog, it "rolls over." My 400 setting was supposed to be a mid speed (sent as 155) which turned out to be a nice mid speed, and the original 1000 (sent as 235) setting just happened to be just about max. I settled on 200, about 80% of full power.

Please fire away with any questions or comments. This weekend I'll download the latest data set and post plots and the CSV of all the data collected. The LUREX is wearing out by now, which will probably impact the catch.

//Mosquito Magnet Defender
//Version 12  5 August 2019
#include <util/delay.h>
#include <Wire.h>
#include <SD.h>
#include <SPI.h>
#include <dht.h>
#include <OneWire.h> 
#include <DallasTemperature.h>
//  Temp sensor driver
dht DHT; 
#define amb_temp 8// Pin ambient temp sensor is connected to
#define igPin 9
#define fanPin 10
#define valvePin 11
#define sd_card 53
#define Temperature_ONE_WIRE_BUS 2 
#include "SSD1306AsciiAvrI2c.h"//OLED Display driver and address
#define OLED_ADDRESS 0x3C //set I2c Address, OLED specific

SSD1306AsciiAvrI2c oled;
OneWire oneWire(2); // DS18B20 temperaure sensors
DallasTemperature sensors(&oneWire);

  bool start = false;
  float chk; 
  int ignit =0;
  float start_time = 360.1;// total igiition cycle until timeout 
  float lightoff = 20.1;// delta T (deg F) for ignition
  float temp = 0;
  float dTemp = 0;
  float aTemp; float a2Temp;
  unsigned long readsec;
  unsigned long initTime;
  int elapsed;
  int x = 0; int y = 0;
  int sec = 0;
  byte iMinute = 0;
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  String stat = "INITIALIZE"; String stat2 = "unassigned";

File myFile;

#define DS3231_I2C_ADDRESS 0x68 // Real time clock 
byte decToBcd(byte val){
  return( (val/10*16) + (val%10) );}
byte bcdToDec(byte val){
  return( (val/16*10) + (val%16) );}


void setup(){
  Serial.begin(19200);
  initTime = millis()/1000;
  sensors.begin(); 
  delay(2000);
  get_temps();
  
  pinMode(sd_card, OUTPUT); // SD card init
  Serial.print("Initializing SD card...");
  if (!SD.begin(53)) {
    Serial.println("initialization failed!");
    return;  }
  Serial.println("initialization done.");
  myFile = SD.open("Magnet.txt", FILE_WRITE);   // if the file opened, write to it:
  if (myFile) {
    myFile.println("initializing SD card,  Mosquito Magnet  ");
    myFile.println("loop#,dayofmonth,month,year,Hour,Min,sec,stat,stat2,elapsed,temp,aTemp,dTemp,a2Temp,humidity");
    myFile.close();
  }

  oled.begin(&Adafruit128x64, OLED_ADDRESS); //OLED Display init
  oled.setFont(Adafruit5x7);
  uint32_t m = micros();
  oled.clear();
  
  pinMode(fanPin, OUTPUT);pinMode(igPin, OUTPUT);pinMode(valvePin, OUTPUT);
  analogWrite(fanPin, 175);// Set fan to low speed; range is 0-255
  digitalWrite(igPin, LOW);// igniters off until called
    
  refresh_oled(); //Show initialize screen to check temp sensors
  delay(6000);
}


void loop(){

   get_temps();
   iMinute = minute;
   readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
 
   if (hour <= 15 || hour > 3){ // sleep routine
           stat = "SLEEPING";
           start = false;
           digitalWrite(valvePin, LOW);//propane off
           analogWrite(fanPin, 200);// Set fan to mid speed
   }
           
   else {  // trapping routine
       
       if (!start){ignite_cycle();} // runs ignition if this is the first loop passed the start time 
       stat = "TRAPPING";

       if (dTemp < lightoff -1){shut_down();}  // shuts down if the hot section is not above ambient by lightoff delta
    }
    
    file_write();       
    serial_write();
    refresh_oled();
}


void ignite_cycle(){
    myFile = SD.open("Magnet.txt", FILE_WRITE);
    myFile.println("loop#,elapsed,temp,aTemp,dTemp,a2Temp,stat,stat2");myFile.close();
    stat = "IGNITION";
    digitalWrite(valvePin, HIGH);//propane on
    digitalWrite(igPin,HIGH); // start igniter
    Serial.println("inside ignite_cycle"); 
    initTime = millis()/1000;
    x = 0;  
    
    while (elapsed < start_time && dTemp < lightoff) {
        x++;
        readsec = millis()/1000;
        elapsed = (readsec - initTime); // provides run time
        get_temps();
        
        Serial.print("IGNITION   dTemp "); Serial.println(dTemp); Serial.print("temp "); Serial.println(temp); 
        Serial.print("aTemp "); Serial.println(aTemp); Serial.print("time "); Serial.println(elapsed); 
    
        myFile = SD.open("Magnet.txt", FILE_WRITE);
        myFile.print(x); myFile.print(",");myFile.print(elapsed); myFile.print(","); myFile.print(temp); myFile.print(","); myFile.print(aTemp); myFile.print(",");myFile.print(dTemp);
        myFile.print(","); myFile.print(a2Temp); myFile.print(","); myFile.print(stat); myFile.print(","); myFile.println(stat2);
        myFile.close(); 
        
          oled.clear(); oled.set2X();
          oled.println(stat); oled.set1X();oled.println();
          oled.print(temp); oled.print("    ");oled.println(dTemp);
          oled.print("temp"); oled.println("     dTemp"); oled.println();
          oled.print(" Ignition time: "); oled.println(elapsed); oled.println();
    }

    digitalWrite(igPin,LOW); // stop igniter

   
    if (elapsed <= start_time){
          start = true;
          stat2 = "Good Ignition"; 
          digitalWrite(igPin, LOW);
          analogWrite(fanPin, 200);// Set fan to mid speed
          Serial.println(stat2);oled.println(stat2); delay(1000);}
    else {start = false;
          stat2 = "No Ignition"; Serial.println(stat2);oled.println(stat2);
          shut_down(); }
}

 // Real time clock setup
void readDS3231time(byte *second,byte *minute,byte *hour,
  byte *dayOfWeek,byte *dayOfMonth,byte *month,byte *year){
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}


void shut_down(){
      stat = "SHUTDOWN ";
      digitalWrite(valvePin, LOW);//propane off
      digitalWrite(igPin, LOW);//be sure ignition is off
      analogWrite(fanPin, 245);// Set fan to high speed
      x = 0;
      
      while (x < 2400){// 600 = 1 hr;  cool down; dry out any trapped biters 
         x++; 
           get_temps();
           serial_write();
           
           iMinute = minute;
           readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
           
           file_write();
           refresh_oled();
      }
      analogWrite(fanPin, LOW);// turn fan off
      stat = "HALT";
      Serial.println(stat);
      refresh_oled();
      while(1); //forever loop
}

void get_temps(){
  sensors.requestTemperatures(); 
  temp = sensors.getTempFByIndex(1);// Hot location initial temp
  aTemp = sensors.getTempFByIndex(0);// Ambient location initial temp
  dTemp = temp - aTemp;
  chk = DHT.read11(amb_temp);
  a2Temp = DHT.temperature*1.8+32;
  delay(2000);
}

void file_write() {
       if (iMinute != minute){
            y++;
            myFile = SD.open("Magnet.txt", FILE_WRITE);  
            myFile.print(y); myFile.print(","); myFile.print(dayOfMonth); myFile.print(","); myFile.print(month); myFile.print(",");myFile.print(year);
            myFile.print(","); myFile.print(hour); myFile.print(","); myFile.print(minute); myFile.print(","); myFile.print(second); myFile.print(",");
            myFile.print(stat); myFile.print(","); myFile.print(stat2); myFile.print(","); myFile.print(elapsed); myFile.print(",");   
            myFile.print(temp); myFile.print(","); myFile.print(aTemp); myFile.print(","); myFile.print(dTemp); myFile.print(",");myFile.print(DHT.humidity);
            myFile.println(",");
            myFile.close(); 
       }
}

void refresh_oled(){ //Push data to the OLED display
        oled.clear(); oled.set2X(); oled.println(stat);oled.set1X();
        oled.print(temp); oled.print("  ");oled.print(aTemp);oled.print("  ");oled.println(DHT.humidity);
        oled.print(" temp"); oled.println("   ambt   humid.");  oled.println();
        oled.print(hour, DEC); oled.print(":");
        oled.print(minute, DEC); oled.print(":");
        oled.print(second, DEC);oled.println(" ");
        oled.print("Loop#");oled.print(x);oled.print(" Elapse:");oled.println(elapsed);
        oled.println(stat2);
}
        
void serial_write(){
        Serial.print(stat);Serial.print("  Temp = ");  Serial.print(temp); Serial.print(" Amb Temp = ");  Serial.print(aTemp);
        Serial.print(" dTemp = ");  Serial.print(dTemp);Serial.print("   Humidity = ");  Serial.println(DHT.humidity);
        Serial.print(hour, DEC); Serial.print(":"); Serial.print(minute, DEC); Serial.print(":"); Serial.print(second, DEC);Serial.println(" ");
        Serial.print(month, DEC);Serial.print("/"); Serial.print(dayOfMonth, DEC);Serial.print("/"); Serial.print(year, DEC);Serial.println();
}
Re: Defender Arduino Design
August 08, 2019 10:46AM
Congratulations on your new system! Did you post a schematic diagram? Do you have time to add a page to our wiki?
Re: Defender Arduino Design
August 11, 2019 06:24PM
I have been running a bunch of tests using the amazing power of the Arduino to command all kinds of combinations of fan speed, cool down times, and ignition sequences.

Is anyone proficient on the circuit diagram tools that would want to tackle the schematic? I downloaded Fritzing, but there’s a decent learning curve to it…

The Real Time Clock feature works really well. The propane tank should last 35 days or so now- more than the Lurex. The catch rate is at the levels of previous years, so the propane down time in the non-catching hours seems to make sense.





Attached is the last CSV for a five day run, and a couple plots showing it works as planned. Beside the dozen or so light offs previous to V12, the latest 5-day run had five flawless lightoffs- in itself a full season for most users. After downloading the SD card and squirting another small update, there was yet another worry-free lightoff. This unit definitely gets stored indoors this winter!

MAGNET_8-10-2019.csv

The substantive change made in the code was just three lines. With all the precise data recorded during lightoff, it was obvious to me that the igniter was being powered for far longer than necessary. In addition to unneeded igniter wear, the MOSFET heat was a concern. This is partly due to the hot section temperature sensor being on the outside of the high-thermal-mass metal fins- the the temp rise is lagging quite a bit. The revised code stores the initial hot section temp as iTemp, then looks for change of five degrees, but running at least 120 seconds. When both those conditions are met, the igniter is powered down. I left the ignite_cycle still running for the 360.1 seconds- I wanted the dTemp to get sufficiently high before jumping into the main loop.

Another small fix was actually an error in the code for the sleep mode: I used “or” (||) instead of “and” (&&) for the IF statement checking the RTC hours. The Magnet shut down at midnight vice 4:00 AM because of this, not too much of a change, honestly.

One thing I may do is actually write to two different files during ignition; the main one (“magnet.txt”) at a one minute sampling rate with all the regular variables, and a new on that only has all the ignition cycles and no other modes. This will make it much easier to do data analysis. As everyone knows- the real key to these things is the lightoff sequence.

Fundamentally, I believe that the stock control system for the Mosquito Magnet falls far short of what is needed to get consistent operation. Using such a low power microcontroller to handle all the logic, and a single thermistor, is not sufficient for the system to “understand” what is really going on. There are tons of YouTube videos, write ups, blogs, etc. to address getting/keeping the Mosquito Magnet running. The system is so fundamentally simple, it is hard to believe that most start problems are clogging, high ambient temps, etc. My propane grill with electronic ignition is way, way more reliable. An investment of $45 for a DIYer provides the ability to have max control is worth every cent if you want the Mosquito Magnet to work consistently. Shave $15 off that if you don’t want the display or SD card, though compared to the cost of fuel and attractant, it makes sense to include them.

I honestly think the repeated disassembly and handling and cleaning of the individual components may induce problems, beyond the already sub-par control system. Since going to the Mega, there have been ZERO lightoff issues in the now 7-year-old Defender, and all I changed was the igniter (the thermistor died before- it is no longer used). It has never shut down, except when I deliberately tested the ignition detection code by turning the tank valve off. No CO2 cartridges have been used except the first lightoff attempt this year, before going to the Mega. That included a couple days where it started at 95+deg F ambient, which seems to be a problem with the stock thermistor, based on the blog entries. I also wonder about the power controls on the stock board- maybe that's where overheating is occurring. So far, the Arduino Mega handles the heat fine. Just my two cents.



Edited 2 time(s). Last edit at 08/11/2019 11:19PM by beads.
Re: Defender Arduino Design
August 12, 2019 01:38PM
You are certainly right about the constant disassembly and reassembly itself causing problems. I have had to reattach the power connector to the controller twice (or thrice?), and the power switch assembly failed because of too much stress on the cheap switch contacts during handling. This was fixed by "rebuilding" the switch wafer, then taping the 4 wires from the switch together about 5 cm away from the switch so that any handling stress would not torture any one individual switch contact causing it to become intermittent.

I wish I could say that my defender's startup was reliable. Now, it won't start at all, and I am away from home. The only thing not replaced or overhauled is the tank regulator, some adjustable low pressure device that I cannot find. Only fixed 11 water column regulators, or high pressure 1-20 psi devices. I remember that 1 psi is about 28 WC, so a 1-20 psi unit would not be precise enough for the trap. Also, I don't know the original pressure spec, which makes the problem worse. Any ideas on the correct gas pressure? I could order a new one and have it there for when I return next week. Fortunately, I have a new-ish Patriot running, and I am hoping that will take up some of the slack.

I used KiCad eeschema to make the Defender and Liberty schematics a few years go. It was fairly easy to learn and use. I have access to professional software (which is hard to learn, and expensive), but cannot use them for this project. How about posting your hand-drawn diagrams, and perhaps someone can take a crack at it.

I like the idea of saving propane and electricity, but worry about the igniter wearing out. I believe the heat up and cool down are the main stressors (like an incandescent bulb), compared with being on the 2 minutes, but I could be wrong. On the other hand, I have been bothered by mosquitoes outside even at high noon on a damp cloudy day, or under a tree. Also late at night and in the early morning. High noon under the blazing sun is the only condition in which my Defender catches nothing.

It would be great if you worked on your idea for a close range mosquito detector, which I could implement and include in the data stream. Wouldn't it be great if it could hear mosquitoes attracted to the lure without the trap running, and then turn on the fan to suck them in? No propane at all!
Re: Defender Arduino Design
August 15, 2019 01:29AM
Here is some cool data from the fan speed tests and the igniter sequencing. During the low fan speed lightoff, the initial temp rise was faster (see second chart), but then it did not increase like the higher fan speeds. The fan speed has some interesting results: the dTemp clearly varies directly with fan speed. In that fan speed run (V13), the fan decreased in power by 10 units of 255 about every ten minutes, ending at about half power. The PWM value is cut in half for the plot to make the chart easier to read (double the chart value to get what the Mega was using)




Reducing the igniter power-on time has worked fine with five lightoffs, including a normal start at 85F ambient today. That may be important because the way I have it set now it will do 90 lightoffs per season, vice four last year (of course only when it worked). In the quiet late evenings, I have monitored the Magnet during start up, when the solenoid can easily heard to click, then a couple seconds after the “IGNITION” is displayed on the OLED, a faint pop can often be heard that tells me right away there is a good lightoff.



Some raw lightoff data. The igniter shuts off after 120 seconds AND 3.0 deg rise in iTemp

elapsed temp aTemp Dtemp iTemp Idtemp stat stat2
114 86.79 83.86 2.92 84.43 2.36 IGNITION unassigned
116 87.01 83.86 3.15 84.43 2.58 IGNITION unassigned
119 87.24 83.97 3.26 84.43 2.81 IGNITION unassigned
122 87.35 83.97 3.38 84.43 2.92 IGNITION unassigned
124 87.57 84.09 3.49 84.43 3.14 IGNITION igniter off
127 87.69 84.09 3.6 84.43 3.26 IGNITION igniter off
130 87.91 84.09 3.83 84.43 3.48 IGNITION igniter off
133 88.14 84.09 4.05 84.43 3.71 IGNITION igniter off
135 88.36 84.09 4.28 84.43 3.93 IGNITION igniter off
138 88.59 84.09 4.5 84.43 4.16 IGNITION igniter off

Do I need to post the latest V14 code?

I completely missed a key factor in detecting the mosquitoes in the trap. I looked at the trap when the screened element was removed with no airflow so the mosquitoes flew round freely. However, the Defender the fan draws the weak flying mosquitoes against the metal mesh during operation, so they are not detectable as flyers. The Doppler was not really optimized for short range close targets, but the answer may by an optical sensor that is installed just before the biters get into the trap. I’m thinking of 3D printing a white conformal tube that uses sensitive optical sensors to count the mosquitoes as they pass through a beam or even a spoiled laser projected against a photodiode array.

Running the igniter for only 120 seconds seems to be working fine- there have been five more perfect ignitions in the latest run, including a start at 85F ambient today. That puts it at 31 good ignitions with zero failures since going with the Arduino Mega. That matches the previous six year total!!! The new code worked great for writing ignition data to its own .TXT file at a high rate, while still doing the one minute updates to the main file. Below is the latest data from the new ignition file from a four day run.





Edited 4 time(s). Last edit at 08/17/2019 11:29AM by beads.
Re: Defender Arduino Design
August 23, 2019 02:10PM
I was away on vacation. Now I have more time to spend on this project.

Definitely please do post your source revisions and a schematic when you have time.

I have to check the shopping list. It was getting pricey...

Thanks.
Re: Defender Arduino Design
August 31, 2019 06:23PM
Sorry for the delay- I’ve been out of the country and unable to write updates. Right before I left for vacation, the Mega Defender stopped working- the OLED screen went blank. Troubleshooting revealed that the igniter MOSFET had failed closed- leaving the igniter on for a couple hours, at which point the female portion of the 5.5mm power adapter actually melted.



In an earlier post, I had mentioned how hot the igniter MOSFET was getting, which motivated me to more than double the size of the aluminum heat sink. Though I measured the igniter current draw at just over 3.7A, it may have been more. Using a digital power supply for such measurements is not always the best approach. The old MOSFET shows signs of scalding in the picture below, and one of the red wires has some melted insulation, so it must have been REALLY hot. The igniter MOSFET was replaced with an IRL7833, rated at a whopping 150A. A pack of four costs $8.40 on Amazon.



https://www.amazon.com/gp/product/B071J39678/ref=ppx_yo_dt_b_asin_title_o01_s00?ie=UTF8&psc=1

The new MOSFET barely gets warms after one full minute, so that should solve the problem. If you buy the four pack, the other two devices (fan and propane valve) will be a no brainer using the same IRL 7833s.

The Fritzing Arduino diagram is far from a work of art, but it should make things clearer. That diagram will be attached in the next post, along with the latest code. PowerPoint was used to label the devices and allowed edits easier than some tools.

There was no need to add another temperature sensor on the igniter MOSFET after bumping up to the much larger version. A third option would be to use a relay designed for Arduinos. Also, since the igniter on time has been cut to 45 seconds, it is likely the lower duty cycle will prolong the life of the MOSFET. I got 41 consecutive ignitions out of the smaller MOSFET before it failed: that’s years’ worth of usage for non-modified Mosquito Magnets. The 42nd perfect lightoff was this morning with the replaced MOSFET.

The total cost of the Mega Defender mod seems pretty reasonable, compared to LUREX and propane each month. In fact, it should pay for itself in reduced propane use during low catch hours in just over a season. There may be cheaper ways to buy the components, like Mouser.com.





Edited 1 time(s). Last edit at 08/31/2019 06:41PM by beads.
Re: Defender Arduino Design
August 31, 2019 07:04PM
Here’s the Arduino Mega wiring diagram. I doubled checked things, but there could still be errors. There are still tons of ports available for other sensors, and the memory usage is 22% for dynamic memory, and only 10% for program storage. The DHT11 sensor is still there- I like having the humidity recording- who knows when that data may be useful. The DHT11 has zero input on the function of the Mega Defender, however.



Below is posted code version 14, which has been rock solid. It includes the separate SD card file for ignition cycles and the twice a day power up. It sleeps about 12 hours a day, which should double propane life. On the other hand, it is very easy to modify the sleep times for your particular area.

There has been no progress on my end in creating a counting system for trapped mosquitoes. It is a very tough problem- those little guys are really small and lightweight. The acoustic detection may be the best bet, but there is so much ambient noise from the fan that the SNR is probably too low.

//Mosquito Magnet Defender
//Version 14  11 August 2019
#include <util/delay.h>
#include <Wire.h>
#include <SD.h>
#include <SPI.h>
#include <dht.h>
#include <OneWire.h> 
#include <DallasTemperature.h>
//  Temp sensor driver
dht DHT; 
#define amb_temp 8// Pin ambient temp sensor is connected to
#define igPin 9
#define fanPin 10
#define valvePin 11
#define sd_card 53
#define Temperature_ONE_WIRE_BUS 2 
#include "SSD1306AsciiAvrI2c.h"//OLED Display driver and address
#define OLED_ADDRESS 0x3C //set I2c Address, OLED specific

SSD1306AsciiAvrI2c oled;
OneWire oneWire(2); // DS18B20 temperaure sensors
DallasTemperature sensors(&oneWire);

  bool start = false;
  float chk; 
  int ignit =0;
  float start_time = 360.1;// total igiition cycle until timeout 
  float lightoff = 10.1;// delta T (deg F) for ignition
  float temp = 0; float iTemp;
  float dTemp = 0;
  float aTemp; float a2Temp;
  unsigned long readsec;
  unsigned long initTime;
  int elapsed;
  int x = 0; int y = 0;   
  int sec = 0;
  byte iMinute = 0;
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  String stat = "INITIALIZE"; String stat2 = "unassigned";

File myFile;

#define DS3231_I2C_ADDRESS 0x68 // Real time clock 
byte decToBcd(byte val){
  return( (val/10*16) + (val%10) );}
byte bcdToDec(byte val){
  return( (val/16*10) + (val%16) );}


void setup(){
  Serial.begin(19200);
  Serial.println("begin initialization");
    
  pinMode(fanPin, OUTPUT);pinMode(igPin, OUTPUT);pinMode(valvePin, OUTPUT);
  analogWrite(fanPin, 170);// Set fan to mid speed; range is 0-255
  digitalWrite(igPin, LOW);// igniters off until called
  
  sensors.begin(); 
  delay(2000);
  get_temps();
  
  pinMode(sd_card, OUTPUT); // SD card init
  Serial.print("Initializing SD card...");
  if (!SD.begin(53)) {
    Serial.println("initialization failed!");
    return;  }
  Serial.println("initialization done.");
  myFile = SD.open("Magnet.txt", FILE_WRITE);   // if the file opened, write to it:
  if (myFile) {
    myFile.println("initializing SD card,  Mosquito Magnet 14");
    myFile.println("loop#,dayofmonth,month,year,Hour,Min,sec,stat,stat2,temp,aTemp,dTemp,a2Temp,fan speed");
    myFile.close();
  }
    myFile = SD.open("ignition.txt", FILE_WRITE);
    myFile.println("loop#,elapsed,temp,aTemp,dTemp,iTemp,stat,stat2,dayofmonth,month,year,Hour,Min,sec");
    myFile.close();

  oled.begin(&Adafruit128x64, OLED_ADDRESS); //OLED Display init
  oled.setFont(Adafruit5x7);
  uint32_t m = micros();
  oled.clear();

  refresh_oled(); //Show initialize screen to check temp sensors
  delay(6000);
}


void loop(){

   get_temps();
   iMinute = minute;
   readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
 
  if ((hour >= 0 && hour < 6) || (hour > 9 && hour < 16)){ // sleep routine
           stat = "SLEEPING";
           start = false;
           digitalWrite(valvePin, LOW);//propane off
           analogWrite(fanPin, 205);// Set fan to mid-high speed
   }
           
   else {  // trapping routine
       
       if (!start){ignite_cycle();} // runs igition if this is the first loop passed the start time 
       stat = "TRAPPING";

       if (dTemp < lightoff -1){shut_down();}  // shuts down if the hot section is not above ambient by lightoff delta
         
    }
    
    file_write();       
    serial_write();
    refresh_oled();
}


void ignite_cycle(){
    stat = "IGNITION";
    digitalWrite(valvePin, HIGH);//propane on
    digitalWrite(igPin,HIGH); // start igniter
    Serial.println("inside ignite_cycle"); 
    initTime = millis()/1000;
    get_temps();
    iTemp = temp;
       
    while (elapsed < start_time && dTemp < lightoff) {
        x++;
        iMinute = minute;
        readsec = millis()/1000;
        elapsed = (readsec - initTime); // provides run time
        get_temps();
        readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);

            if ((temp-iTemp) > 1.55 && elapsed > 45) {
              digitalWrite(igPin, LOW);  //  turn off igniter, stay in close monitoring loop til start_time is reached         
              analogWrite(fanPin, 210);// Set fan to mid-high speed
              stat2 = "igniter off";
            }
        
        Serial.print("IGNITION   dTemp "); Serial.println(dTemp); Serial.print("temp "); Serial.println(temp); 
        Serial.print("aTemp "); Serial.println(aTemp); Serial.print("time "); Serial.println(elapsed); 
    
        myFile = SD.open("ignition.txt", FILE_WRITE);
        myFile.print(x); myFile.print(",");myFile.print(elapsed); myFile.print(","); myFile.print(temp); myFile.print(","); myFile.print(aTemp); myFile.print(",");myFile.print(dTemp);
        myFile.print(","); myFile.print(iTemp); myFile.print(","); myFile.print(stat); myFile.print(","); myFile.println(stat2);myFile.print(","); myFile.print(dayOfMonth); myFile.print(","); myFile.print(month); myFile.print(",");myFile.print(year);
        myFile.print(","); myFile.print(hour); myFile.print(","); myFile.print(minute); myFile.print(","); myFile.print(second);
        myFile.close(); 

        file_write(); // also write to main file at the one minute interval
        
          oled.clear(); oled.set2X();
          oled.println(stat); oled.set1X();oled.println();
          oled.print(temp); oled.print("    ");oled.println(dTemp);
          oled.print("temp"); oled.println("     dTemp"); oled.println();
          oled.print(" Ignition time: "); oled.println(elapsed); oled.println();
    }

    digitalWrite(igPin,LOW); // stop igniter

   
    if (elapsed <= start_time){
          start = true;
          stat2 = "Good Ignition"; 
          digitalWrite(igPin, LOW);
          analogWrite(fanPin, 210);// Set fan to mid-high speed
          Serial.println(stat2);oled.println(stat2); delay(1000);}
    else {start = false;
          stat2 = "No Ignition"; Serial.println(stat2);oled.println(stat2);
          shut_down(); }
}

 // Real time clock setup
void readDS3231time(byte *second,byte *minute,byte *hour,
  byte *dayOfWeek,byte *dayOfMonth,byte *month,byte *year){
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}


void shut_down(){
      stat = "SHUTDOWN ";
      digitalWrite(valvePin, LOW);//propane off
      digitalWrite(igPin, LOW);//be sure ignition is off
      analogWrite(fanPin, 245);// Set fan to high speed
      x = 0;
      
      while (x < 2400){// 600 = 1 hr;  cool down; dry out any trapped biters 
         x++; 
           get_temps();
           serial_write();
           
           iMinute = minute;
           readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
           
           file_write();
           refresh_oled();
      }
      analogWrite(fanPin, LOW);// turn fan off
      stat = "HALT";
      Serial.println(stat);
      refresh_oled();
      while(1); //forever loop
}

void get_temps(){
  sensors.requestTemperatures(); 
  temp = sensors.getTempFByIndex(1);// Hot location initial temp
  aTemp = sensors.getTempFByIndex(0);// Ambient location initial temp
  dTemp = temp - aTemp;
  chk = DHT.read11(amb_temp);
  a2Temp = DHT.temperature*1.8+32;
  delay(2000);
}

void file_write() {
       if (iMinute != minute){
            y++;
            myFile = SD.open("Magnet.txt", FILE_WRITE);  
            myFile.print(y); myFile.print(","); myFile.print(dayOfMonth); myFile.print(","); myFile.print(month); myFile.print(",");myFile.print(year);
            myFile.print(","); myFile.print(hour); myFile.print(","); myFile.print(minute); myFile.print(","); myFile.print(second); myFile.print(",");
            myFile.print(stat); myFile.print(","); myFile.print(stat2); myFile.print(",");
            myFile.print(temp); myFile.print(","); myFile.print(aTemp); myFile.print(","); myFile.print(dTemp); myFile.print(",");myFile.print(DHT.humidity);
            myFile.println(",");
            myFile.close(); 
       }
}

void refresh_oled(){ //Push data to the OLED display
        oled.clear(); oled.set2X(); oled.println(stat);oled.set1X();
        oled.print(temp); oled.print("  ");oled.print(aTemp);oled.print("  ");oled.println(DHT.humidity);
        oled.print("temp"); oled.println("   ambt   humid.");  oled.println();
        oled.print(hour, DEC); oled.print(":");
        oled.print(minute, DEC); oled.print(":");
        oled.print(second, DEC);oled.println(" ");
        oled.print("Loop# ");oled.print(x);oled.print(" Elapsed:");oled.println(elapsed);
        oled.println(stat2);
}
        
void serial_write(){
        Serial.print(stat);Serial.print("  Temp = ");  Serial.print(temp); Serial.print(" Amb Temp = ");  Serial.print(aTemp);
        Serial.print(" dTemp = ");  Serial.print(dTemp);Serial.print("   Humidity = ");  Serial.println(DHT.humidity);
        Serial.print(hour, DEC); Serial.print(":"); Serial.print(minute, DEC); Serial.print(":"); Serial.print(second, DEC);Serial.println(" ");
        Serial.print(month, DEC);Serial.print("/"); Serial.print(dayOfMonth, DEC);Serial.print("/"); Serial.print(year, DEC);Serial.println();
}


The Version 15 update is pretty far along. That new code calculates sunrise and sunset based on the day and latitude, then looks at run time as a function of a floating variable hours vice bytes. I feel really comfortable with the lightoff sequence now, as it has worked flawlessly over forty times now, in all kinds of ambient temperature conditions. The new code will also display total run time in decimal days, so you can track how far down the propane tank should be.

Below is the last run before replacing the MOSFET. It is interesting to see the delta temp (dTemp) stays very consistent at about 40 deg F, regardless of ambient temps.



If there are any questions please let me know. Also, any feedback would be great... this is definitely a hacked-together project and there are many places for improvements.

Happy Hunting!



Edited 1 time(s). Last edit at 09/01/2019 01:47AM by beads.
Hot MosFETs
September 02, 2019 12:03AM
Good that your are making progress.

Sorry I missed the part in your earlier post about the igniter mosfet getting too hot to touch. Looking at the spec for the
(now obsolete) RFP30N06LE mosfet you first used, it looks like any gate drive over about 3 volts should be sufficient to handle 20 amps of current. A 5 volt drive should result in a 0.047 ohm Rds, and with 10 Amps continuous current, just 0.47 watts in the package, so your observed extreme overheating doesn't make sense to me. Perhaps these units sold on Amazon didn't meet spec somehow. or perhaps there was too much resistance in the common ground wire, dropping the effective gate drive voltage. In any case, it's good that the 150 amp units you are now using don't get hot at all.

Earlier today, I updated the NodeMCU construction wiki page (see Defender NodeMCU Design) with tests to make sure the original controller drivers don't get hot. What a coincidence! I also went on vacation, had a silly failure just before departure, and then later was frustrated when I could not restart my Defender remotely. I was aghast that the problem turned out to be an empty propane tank, but fortunately much less of a worry than a shorted driver and a melted power supply connector. Those igniters sure take a lot of juice.

Your project may not need a wiki article with all of the information you have posted here, but I still invite you to create one on this site. It does not have to be so elaborate as the NodeMCU, which has grown to be quite a project. On the other hand, you may find yourself tweaking your wiki constantly.
Re: Defender Arduino Design
September 07, 2019 01:29AM
This is - to me at least- the wrap up of this project. The sunrise/sunset calculations worked pretty well, but after adding tons of variables and running into issues with BCD (Binary Coded Decimal) conversion, it became obvious that the summer- when the Magnet is running, has small variations in sunset and sunrise time. Since the wide window on the run times at sunrise and sunset is arbitrary to begin with, the actual time change for sunrise/sunset is in the noise. The conversion of the time to decimal hours was not intuitive - the RTC uses BCD notation for the two-digit data packets (nibbles), which cannot be used in standard floating point math.

To ease testing, I built a second Mega Defender board, and included a couple images in the photo album.


PHOTOS


The biggest change to V15 is the use of the “hours” variables to switch the propane on and off, and provide even more data on usage. What I really like is the cumulative propane-on time (“propane_hours” variable) that will track total on time. The OLED now displays propane run time in days to thee decimal places, so getting and idea of how long the tank lasts should be very easy.

The output of the twice-a-day lightoffs is pretty cool. The rise in temp in the morning as well as the decrease in temps in the afternoon are clearly visible. The new "hours" variable shows as the blue sawtooth pattern; it drops to zero at midnight, which also coincides with the programmed sleep time.




The IGNITION.TXT file does a great job capturing the data for each six minute ignition cycle. The temp rise has been set at 1.55 deg F, based on looking at more than a dozen successful lightoffs in many ambient temperature conditions. Once the Mega sees that delta, AND at least 45 seconds have passed, the igniter is shutoff. It stays inside the ignition method until up to six minutes (it kick outs when dTemp exceeds 10.1 deg F) to record the more frequent temperature data (every 2.8 seconds vice every minute). Also attached is the CSV file for the MAGNET.txt runs that were used to generate the plots.




MAGNET_9-4-2019_CSV.csv

I swapped out the tank after flashing V15 to measure exactly how many hours a fresh tank lasts, though the tank refills themselves have variation in propane quantity. I still have not run a CO2 cleanout cartridge since the beginning of the season, and yet it starts every single time, twice a day.

BOTTOM LINE: The Mega Defender runs like an absolute champ. It is seven years old, and the only thing I’ve replaced is the igniter. Since the last post, it has 10 more perfect light-offs, and survived some very nasty thunderstorms without a hiccup. I am convinced that the issues with the poor reliability- specifically starts- are directly attributable to the legacy Defender control system. It seems impossible that the system can get by with a single thermistor as a system input. Based on the current 47% of ratings are one-star on Amazon, almost all for poor reliability and failure to start after one or two seasons, it is safe to say that Mosquito Magnet has a problem that they have failed to address.

Finally- here's Mega Defender V15 code. Unless something funky comes up, this is the last release. It works really well. It has over 60 consecutive lightoffs with no hiccups. It makes my backyard completely livable again.

//Mosquito Magnet Defender
//Version 15  4 Sept 2019
#include <Wire.h>
#include <SD.h>
#include <SPI.h>
#include <dht.h>
#include <OneWire.h> 
#include <DallasTemperature.h>

#define amb_temp 8// ambient DHT temp/humidity
#define igPin 9 //igniter
#define fanPin 10 // fan
#define valvePin 11 // propane valve
#define sd_card 53
#define Temperature_ONE_WIRE_BUS 2 // good temp sensors
#include "SSD1306AsciiAvrI2c.h"//OLED Display driver and address
#define OLED_ADDRESS 0x3C //set I2c Address, OLED specific

dht DHT; 
SSD1306AsciiAvrI2c oled;
OneWire oneWire(2); // DS18B20 temperaure sensors
DallasTemperature sensors(&oneWire);

  bool start = false;
  float chk; 
  int ignit =0;
  float start_time = 360;// total ignition cycle until timeout 
  float lightoff = 10.1;// delta T (deg F) for ignition
  float temp = 0; float iTemp;
  float dTemp = 0;
  float aTemp; float a2Temp;
  unsigned long readsec;
  unsigned long initTime;
  int elapsed; 
  float propane_hours, total_hours, propane_days, total_days;
  float x = 0, y = 0, z = 0;
  int sec = 0;
  byte iMinute = 0;
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  float hours, dec_hour, dec_min;
  String stat = "INITIALIZE"; String stat2 = "unassigned";

File myFile;

#define DS3231_I2C_ADDRESS 0x68 // Real time clock 
byte decToBcd(byte val){
  return( (val/10*16) + (val%10) );}
byte bcdToDec(byte val){
  return( (val/16*10) + (val%16) );}


void setup(){
  Serial.begin(19200);
  initTime = millis()/1000;
    
  pinMode(fanPin, OUTPUT);pinMode(igPin, OUTPUT);pinMode(valvePin, OUTPUT);
  analogWrite(fanPin, 170);// Set fan to mid speed; range is 0-255
  digitalWrite(igPin, LOW);// igniters off until called
  
  sensors.begin(); 
  delay(2000);
  get_temps();
  
  pinMode(sd_card, OUTPUT); // SD card init
  Serial.print("Initializing SD card...");
  if (!SD.begin(53)) {
    Serial.println("initialization failed!");
    return;  }
  Serial.println("initialization done.");
  myFile = SD.open("Magnet.txt", FILE_WRITE);   // if the file opened, write to it:
  if (myFile) {
    myFile.println("initializing SD card,  Mosquito Magnet Mega Defender V15");
    myFile.println("loop#,hours,dayofmonth,month,year,hour,min,sec,stat,stat2,temp,aTemp,dTemp,a2Temp,total_hrs,propane_hrs");
    myFile.close();
  }
    myFile = SD.open("ignition.txt", FILE_WRITE);
    myFile.println("loop#,elapsed,temp,aTemp,dTemp,iTemp,stat,stat2,dayofmonth,month,year,Hour,Min,sec");
    myFile.close();

  oled.begin(&Adafruit128x64, OLED_ADDRESS); //OLED Display init
  oled.setFont(Adafruit5x7);
  uint32_t m = micros();
  oled.clear();

  refresh_oled(); //Show initialize screen to check temp sensors
  delay(6000);
}


void loop(){

   get_temps();
   iMinute = minute;
   readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
   dec_min = minute; dec_hour = hour;   
   hours = dec_hour + (dec_min/60);

  if ((hours > 0.25 && hours < 6) || (hours > 10 && hours < 16.25)){ // sleep routine; sleeps late at night and mid day
           stat = "SLEEPING";
           start = false;
           digitalWrite(valvePin, LOW);//propane off
           analogWrite(fanPin, 205);// Set fan to mid-high speed
   }
           
   else {  // trapping routine
       
       if (!start){ignite_cycle();} // runs ignition if this is the first loop passed the start time 
       stat = "TRAPPING";

       if (dTemp < lightoff -1){shut_down();}  // shuts down if the hot section is not above ambient by lightoff delta
         
    }
    
    file_write();       
    serial_write();
    refresh_oled();
}


void ignite_cycle(){
    stat = "IGNITION";
    digitalWrite(valvePin, HIGH);//propane on
    digitalWrite(igPin,HIGH); // start igniter
    Serial.println("inside ignite_cycle"); 
    initTime = millis()/1000;
    get_temps();
    iTemp = temp;
    
    while (elapsed < start_time && dTemp < lightoff) {
        x++;     
        iMinute = minute;
        readsec = millis()/1000;
        elapsed = (readsec - initTime); // provides run time
        get_temps();
        readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);

        if ((temp-iTemp) > 1.55 && elapsed > 45) {
          digitalWrite(igPin, LOW);  //  turn off igniter, stay in ignition monitoring loop til start_time is reached         
          analogWrite(fanPin, 210);// Set fan to mid-high speed
          stat2 = "igniter off";
        }
        
        Serial.print("IGNITION   dTemp "); Serial.println(dTemp); Serial.print("temp "); Serial.println(temp); 
        Serial.print("aTemp "); Serial.println(aTemp); Serial.print("Elapsed "); Serial.println(elapsed); 
    
        myFile = SD.open("ignition.txt", FILE_WRITE);
        myFile.print(x); myFile.print(",");myFile.print(elapsed); myFile.print(","); myFile.print(temp); myFile.print(","); myFile.print(aTemp); myFile.print(",");myFile.print(dTemp);
        myFile.print(","); myFile.print(iTemp); myFile.print(","); myFile.print(stat); myFile.print(","); myFile.print(stat2); myFile.print(","); myFile.print(dayOfMonth); myFile.print(","); myFile.print(month); myFile.print(",");myFile.print(year);
        myFile.print(","); myFile.print(hour); myFile.print(","); myFile.print(minute); myFile.print(","); myFile.println(second);
        myFile.close(); 

        file_write();
        
          oled.clear(); oled.set2X();
          oled.println(stat); oled.set1X();oled.println();
          oled.print(temp); oled.print("    ");oled.println(dTemp);
          oled.print("temp"); oled.println("     dTemp"); oled.println();
          oled.print(" Ignition time: "); oled.println(elapsed); 
          oled.print("hours: ");oled.println(hours);
    }

    digitalWrite(igPin,LOW); // stop igniter

    if (elapsed <= start_time){
          start = true; x = 0;
          stat2 = "Good Ignition"; 
          digitalWrite(igPin, LOW);
          analogWrite(fanPin, 210);// Set fan to mid-high speed
          Serial.println(stat2);oled.println(stat2); delay(1000);}
    else {start = false;
          stat2 = "No Ignition"; Serial.println(stat2);oled.println(stat2);
          shut_down(); }
}

 // Real time clock setup
void readDS3231time(byte *second,byte *minute,byte *hour,
  byte *dayOfWeek,byte *dayOfMonth,byte *month,byte *year){
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());

}

void shut_down(){
      stat = "SHUTDOWN ";
      digitalWrite(valvePin, LOW);//propane off
      digitalWrite(igPin, LOW);//be sure ignition is off
      analogWrite(fanPin, 245);// Set fan to high speed
      x = 0;
      
      while (x < 2400){// 600 = 1 hr;  cool down; dry out any trapped biters 
         x++; 
           get_temps();           
           iMinute = minute;
           readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
              dec_min = minute; dec_hour = hour;
              hours = dec_hour + (dec_min/60);
           serial_write();
           file_write();
           refresh_oled();
      }
      analogWrite(fanPin, LOW);// turn fan off
      stat = "HALT";
      Serial.println(stat);
      refresh_oled();
      while(1); //forever loop
}

void get_temps(){
  sensors.requestTemperatures(); 
  temp = sensors.getTempFByIndex(1);// Hot location initial temp
  aTemp = sensors.getTempFByIndex(0);// Ambient location initial temp
  dTemp = temp - aTemp;
  chk = DHT.read11(amb_temp);
  a2Temp = DHT.temperature*1.8+32;
  delay(2000);
}

void file_write() {
       if (iMinute != minute){
            y++;
            total_hours = y/60; total_days = total_hours/ 24;
            
            if (start){z++; propane_hours = z/60; propane_days = propane_hours/24;} // adds time only if igniited
            
            myFile = SD.open("Magnet.txt", FILE_WRITE);  
            myFile.print(y); myFile.print(",");myFile.print(hours); myFile.print(","); myFile.print(dayOfMonth); myFile.print(","); myFile.print(month); myFile.print(",");myFile.print(year);
            myFile.print(","); myFile.print(hour); myFile.print(","); myFile.print(minute); myFile.print(","); myFile.print(second); myFile.print(",");
            myFile.print(stat); myFile.print(","); myFile.print(stat2); myFile.print(",");   
            myFile.print(temp); myFile.print(","); myFile.print(aTemp); myFile.print(","); myFile.print(dTemp); myFile.print(",");myFile.print(DHT.humidity);
            myFile.print(","); myFile.print(total_hours,2); myFile.print(","); myFile.print(propane_hours,2); 
            myFile.println(","); myFile.close(); 
       }
}

void refresh_oled(){ //Push data to the OLED display
        oled.clear(); oled.set2X(); oled.println(stat);oled.set1X();
        oled.print(temp); oled.print("  ");oled.print(aTemp);oled.print("  ");oled.println(DHT.humidity);
        oled.println(" temp   ambt   humid.");
        oled.print(hour, DEC); oled.print(":");oled.print(minute, DEC); oled.print(":");oled.println(second, DEC);
        oled.print("propane days: ");oled.println(propane_days,3);
        oled.print("time dec_hr:");oled.print(hours,2); 
}
        
void serial_write(){
        Serial.print(stat);Serial.print("  Temp = ");  Serial.print(temp); Serial.print(" Amb Temp = ");  Serial.print(aTemp);
        Serial.print(" dTemp = ");  Serial.print(dTemp);Serial.print("   Humidity = ");  Serial.println(DHT.humidity);
        Serial.print(hour, DEC); Serial.print(":"); Serial.print(minute, DEC); Serial.print(":"); Serial.print(second, DEC);Serial.println(" ");
        Serial.print(month, DEC);Serial.print("/"); Serial.print(dayOfMonth, DEC);Serial.print("/"); Serial.print(year, DEC);Serial.println();
        Serial.print("Hours: ");Serial.print(hours); Serial.print("  run hrs ");Serial.println(total_hours,3);Serial.println();
}



Edited 3 time(s). Last edit at 09/08/2019 02:49AM by beads.
Re: Defender Arduino Design
September 28, 2019 12:52AM
Thanks for your forum posts. I hope your wiki page project is just as informative.

By the way, some of your posts were very helpful to me in fixing the anomalies on my old 2002 Defender. See the blog. (Briefly, the regulator did it.) In particular, your the graphs of the exterior and case temperatures made me realize that the trap internal exhaust temperature is completely dependent on the incoming air temperature. I now measure incoming air and exhaust temperature, and the difference is also nearly constant. I am now testing replacement regulators. Some work well, others don't.
Re: Defender Arduino Design
October 03, 2019 02:03AM
OK- something did come up. Actually, a few things. My wife did not like the “blaring” OLED display that was visible from the kitchen eating area most of the time, so it was time to implement a feature that I had thought about earlier: integrating an HC-05 Bluetooth module (HERE at Amazon for $9) so that the status of the Mega Defender could be checked from almost anywhere in the house using any Android phone. The hours is displayed in decimal 24 system (13.33 is 1:20 PM)


Connect RX from the HC-05 pin 19 on the Mega, and TX to pin 18. Be sure use 3.3V VCC; or use a voltage divider. See pictures for more. One other thing; the standard “Serial.begin(xxx);” command had to be commented out in V16 to allow the BTserial.begin() to function; there may be a work around, but the only time the serial output is used is when the USB cable is connected- very rarely.



The wiring was a mess- I broke or disconnected couple jumpers in the rat’s nest of wires around the Arduino Mega while connecting the Bluetooth module. However, with all the data being fed to the SD card and the OLED, it was very easy to isolate the faults. The Bluetooth App can be downloaded HERE, but you really need to download it through Google Play on your Android Phone. The APP can be customized for the Mega Arduino or really any Arduino project (click on the gear symbol in the upper right). The four digit pairing number for the HC-05 linked above is “1234”- like the airlock code in Spaceballs, with one less digit!



MORE PICTURES HERE

Recent issue: after 81 consecutive worry-free lightoffs over two propane tanks, the first ignition failure occurred. Again, with all the data, it was easy to get an idea of what happened. The igniter that was replaced at the beginning of this season gave up the ghost. It read as an open circuit, indicating an internal failure. Up to code version V13, I had made a poor choice and energized the igniter for 5+ minutes during each and every lightoff, when that clearly wasn’t necessary. Those V13 and prior lightoffs took a serious toll on the lifespan. V15 and later code kills power to the igniter after 45 seconds and 1.55 deg F temperature rise. Even so, the twice a day lightoffs are a heck of a lot more stress on the igniter that normally get used four times per season with four tanks of propane. After replacing the igniter, there have been four consecutive perfect lightoffs with no issues.



Two other things. I cut out the 5.5mm plug/jack; it was getting loose and the plug was not designed for the current draw of the igniter. The power adapter itself allows unplugging on one side, so that “solves” any problem that the 5.5m jack fixed. Also, the blue USB cable running out from the Arduino Mega was no longer reliable after being in the weather for a couple months. There was intermittent connectivity when plugged into the laptop; when swapped with a new USB cable, the connectivity was fixed.

I had an excellent suggestion to install a flammable gas detector inside the housing; that will wait until next year, since this season is almost over. However, as I explained in an earlier post, the risk of any explosion is negligible if used outdoors in open space that cannot trap propane gas.

This is by far the most complicated Arduino set up I’ve worked with, considering the number of output and sensors, plus a bank of MOSFETs to power the main system. The Bluetooth APP is really cool- it is nice to see all the parameters updating while in the house- though it doesn’t transmit to the web for global view, which would be far better. Code V16 is below.

Again, any and all inputs or comments would be appreciated!
//Mosquito Magnet Defender
//Version 16  29 Sept 2019
#include <Wire.h>
#include <SD.h>
#include <SPI.h>
#include <dht.h>
#include <OneWire.h> 
#include <DallasTemperature.h>
#include <SoftwareSerial.h>

#define amb_temp 8// ambient DHT temp/humidity
#define igPin 9 //igniter
#define fanPin 10 // fan
#define valvePin 11 // propane valve
#define sd_card 53
#define Temperature_ONE_WIRE_BUS 2 // good temp sensors
#include "SSD1306AsciiAvrI2c.h"//OLED Display driver and address
#define OLED_ADDRESS 0x3C //set I2c Address, OLED specific

dht DHT; 
SSD1306AsciiAvrI2c oled;
OneWire oneWire(2); // DS18B20 temperaure sensors
DallasTemperature sensors(&oneWire);
SoftwareSerial BTserial(19,18); // RX | TX

  bool start = false;
  float chk; 
  int ignit =0;
  float start_time = 360;// total igiition cycle until timeout
  float lightoff = 10.1;// delta T (deg F) for ignition
  float temp = 0; float iTemp;
  float dTemp = 0;
  float aTemp; float a2Temp;
  unsigned long readsec;
  unsigned long initTime;
  int elapsed; 
  float propane_hours, total_hours, propane_days, total_days;
  float x = 0, y = 0, z = 0;
  int sec = 0;
  byte iMinute = 0;
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  float hours, dec_hour, dec_min;
  String stat = "INITIALIZE"; String stat2 = "unassigned";

File myFile;

#define DS3231_I2C_ADDRESS 0x68 // Real time clock 
byte decToBcd(byte val){
  return( (val/10*16) + (val%10) );}
byte bcdToDec(byte val){
  return( (val/16*10) + (val%16) );}


void setup(){
  //Serial.begin(19200);
  BTserial.begin(9600); 
  initTime = millis()/1000;
    
  pinMode(fanPin, OUTPUT);pinMode(igPin, OUTPUT);pinMode(valvePin, OUTPUT);
  analogWrite(fanPin, 170);// Set fan to mid speed; range is 0-255
  digitalWrite(igPin, LOW);// igniters off until called
  
  sensors.begin(); 
  delay(2000);
  get_temps();
  
  pinMode(sd_card, OUTPUT); // SD card init
  Serial.print("Initializing SD card...");
  if (!SD.begin(53)) {
    Serial.println("initialization failed!");
    return;  }
  Serial.println("initialization done.");
  myFile = SD.open("Magnet.txt", FILE_WRITE);   // if the file opened, write to it:
  if (myFile) {
    myFile.println("initializing SD card,  Mosquito Magnet Mega Defender V16");
    myFile.println("loop#,hours,dayofmonth,month,year,hour,min,sec,hours,stat,stat2,temp,amb_Temp,delta_Temp,a2Temp,total_hrs,propane_hrs,total_days, propane_days");
    myFile.close();
  }
    myFile = SD.open("ignition.txt", FILE_WRITE);
    myFile.println("loop#,elapsed,temp,aTemp,dTemp,iTemp,stat,stat2,dayofmonth,month,year,Hour,Min,sec");
    myFile.close();

  oled.begin(&Adafruit128x64, OLED_ADDRESS); //OLED Display init
  oled.setFont(Adafruit5x7);
  uint32_t m = micros();
  oled.clear();

  refresh_oled(); //Show initialize screen to check temp sensors
  delay(6000);
}


void loop(){

   get_temps();
   iMinute = minute;
   readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
   
   dec_min = minute; dec_hour = hour;    
   hours = dec_hour + (dec_min/60);

  if ((hours > 0.75 && hours < 6) || (hours > 9.5 && hours < 16.25)){ // sleep routine; sleeps late at night and mid day
           stat = "SLEEPING";
           start = false;
           digitalWrite(valvePin, LOW);//propane off
           analogWrite(fanPin, 205);// Set fan to mid-high speed
   }
           
   else {  // trapping routine
       
       if (!start){ignite_cycle();} // runs igition if this is the first loop passed the start time 
       stat = "TRAPPING";

       if (dTemp < lightoff -1){shut_down();}  // shuts down if the hot section is not above ambient by lightoff delta
         
    }
    
    file_write();       
    serial_write();
    refresh_oled();
    bluetooth();
}


void ignite_cycle(){
    stat = "IGNITION";
    digitalWrite(valvePin, HIGH);//propane on
    digitalWrite(igPin,HIGH); // start igniter
    Serial.println("inside ignite_cycle"); 
    initTime = millis()/1000;
    get_temps();
    iTemp = temp;
    stat2 = "igniter on";
    
    while (elapsed < start_time && dTemp < lightoff) {
        x++;     
        iMinute = minute;
        readsec = millis()/1000;
        elapsed = (readsec - initTime); // provides run time
        get_temps();
        readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);

        if ((temp-iTemp) > 1.55 && elapsed > 45) {
          digitalWrite(igPin, LOW);  //  turn off igniter, stay in ignition monitoring loop til start_time is reached         
          analogWrite(fanPin, 210);// Set fan to mid-high speed
          stat2 = "igniter off";
        }
        
        Serial.print("IGNITION   dTemp "); Serial.println(dTemp); Serial.print("temp "); Serial.println(temp); 
        Serial.print("aTemp "); Serial.println(aTemp); Serial.print("Elapsed "); Serial.println(elapsed); 
    
        myFile = SD.open("ignition.txt", FILE_WRITE);
        myFile.print(x); myFile.print(",");myFile.print(elapsed); myFile.print(","); myFile.print(temp); myFile.print(","); myFile.print(aTemp); myFile.print(",");myFile.print(dTemp);
        myFile.print(","); myFile.print(iTemp); myFile.print(","); myFile.print(stat); myFile.print(","); myFile.print(stat2); myFile.print(","); myFile.print(dayOfMonth); myFile.print(","); myFile.print(month); myFile.print(",");myFile.print(year);
        myFile.print(","); myFile.print(hour); myFile.print(","); myFile.print(minute); myFile.print(","); myFile.print(second); myFile.print(","); myFile.println(hours);
        myFile.close(); 

        file_write();
        
          oled.clear(); oled.set2X();
          oled.println(stat); oled.set1X();oled.println();
          oled.print(temp); oled.print("    ");oled.println(dTemp);
          oled.print("temp"); oled.println("     dTemp"); oled.println();
          oled.print(" Ignition time: "); oled.println(elapsed); 
          oled.print("hours: ");oled.println(hours);

          bluetooth();
    }

    digitalWrite(igPin,LOW); // stop igniter

    if (elapsed <= start_time){
          start = true; x = 0;
          stat2 = "Good Ignition"; 
          digitalWrite(igPin, LOW);
          analogWrite(fanPin, 210);// Set fan to mid-high speed
          Serial.println(stat2);oled.println(stat2); delay(1000);}
    else {start = false;
          stat2 = "No Ignition"; Serial.println(stat2);oled.println(stat2);
          shut_down(); }
}

 // Real time clock setup
void readDS3231time(byte *second,byte *minute,byte *hour,
  byte *dayOfWeek,byte *dayOfMonth,byte *month,byte *year){
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());

}

void shut_down(){
      stat = "SHUTDOWN ";
      digitalWrite(valvePin, LOW);//propane off
      digitalWrite(igPin, LOW);//be sure ignition is off
      analogWrite(fanPin, 245);// Set fan to high speed
      x = 0;
      
      while (x < 2400){// 600 = 1 hr;  cool down; dry out any trapped biters 
         x++; 
           get_temps();           
           iMinute = minute;
           readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
              dec_min = minute; dec_hour = hour;
              hours = dec_hour + (dec_min/60);
           serial_write();
           file_write();
           refresh_oled();
           bluetooth();
      }
      analogWrite(fanPin, LOW);// turn fan off
      stat = "HALT";
      Serial.println(stat);
      refresh_oled();
      while(1); //forever loop
}

void get_temps(){
  sensors.requestTemperatures(); 
  temp = sensors.getTempFByIndex(1);// Hot location initial temp
  aTemp = sensors.getTempFByIndex(0);// Ambient location initial temp
  dTemp = temp - aTemp;
  chk = DHT.read11(amb_temp);
  a2Temp = DHT.temperature*1.8+32;
  delay(2000);
}

void file_write() {
       if (iMinute != minute){
            y++;
            total_hours = y/60; total_days = total_hours/24;
            
            if (start){z++; propane_hours = z/60; propane_days = propane_hours/24;} // adds time only if igniited
            
            myFile = SD.open("Magnet.txt", FILE_WRITE);  
            myFile.print(y); myFile.print(",");myFile.print(hours); myFile.print(","); myFile.print(dayOfMonth); myFile.print(","); myFile.print(month); myFile.print(",");myFile.print(year);
            myFile.print(","); myFile.print(hour); myFile.print(","); myFile.print(minute); myFile.print(","); myFile.print(second); myFile.print(","); myFile.print(hours);myFile.print(",");
            myFile.print(stat); myFile.print(","); myFile.print(stat2); myFile.print(",");   
            myFile.print(temp); myFile.print(","); myFile.print(aTemp); myFile.print(","); myFile.print(dTemp); myFile.print(",");myFile.print(DHT.humidity);
            myFile.print(","); myFile.print(total_hours,2); myFile.print(","); myFile.print(propane_hours,2); myFile.print(","); myFile.print(total_days,3); myFile.print(","); myFile.print(propane_days,3);
            myFile.println(","); myFile.close(); 
       }
}

void refresh_oled(){ //Push data to the OLED display
        oled.clear(); oled.set2X(); oled.println(stat);oled.set1X();
        oled.print(temp); oled.print("  ");oled.print(aTemp);oled.print("  ");oled.println(DHT.humidity);
        oled.println(" temp   ambt   humid.");
        //oled.print(hour, DEC); oled.print(":");oled.print(minute, DEC); oled.print(":");oled.println(second, DEC);
        oled.print("propane days: ");oled.println(propane_days,3);
        oled.print("total days: ");oled.println(total_days,3);
        oled.print("current hour: ");oled.print(hours,2); 
}
        
void serial_write(){
        Serial.print(stat);Serial.print("  Temp = ");  Serial.print(temp); Serial.print(" Amb Temp = ");  Serial.print(aTemp);
        Serial.print(" dTemp = ");  Serial.print(dTemp);Serial.print("   Humidity = ");  Serial.println(DHT.humidity);
        Serial.print(hour, DEC); Serial.print(":"); Serial.print(minute, DEC); Serial.print(":"); Serial.print(second, DEC);Serial.println(" ");
        Serial.print(month, DEC);Serial.print("/"); Serial.print(dayOfMonth, DEC);Serial.print("/"); Serial.print(year, DEC);Serial.println();
        Serial.print("Hours: ");Serial.print(hours); Serial.print("  run hrs ");Serial.println(total_hours,3);Serial.println();
}

void bluetooth(){ //Push data through the HC-05 bluetooth module
        BTserial.print(stat);BTserial.print(",");
        BTserial.print(hours,2);BTserial.print(",");
        BTserial.print(temp);BTserial.print(",");
        BTserial.print(aTemp);BTserial.print(",");
        BTserial.print(total_days,3);BTserial.print(",");
        BTserial.print(propane_days,3);BTserial.print(";"); // last output needs to have the ";"
}

Re: Defender Arduino Design
October 03, 2019 03:20PM
Wireless is really great, especially when it's raining.

I think you are going to need much more weatherproofing, but it looks like the unit is going to last this season.

I believe the igniter problem is not so much the length of time it is running, but the number of on/off cycles it endures. It is a factor with incandescent lights. The sudden shock caused by the inrush of current into a cold igniter could be a problem.

When I had an intermittent "power" switch, the trap was constantly restarting, many times per hour. This destroyed the igniter after a few days. I thought the trap was running because I could hear the fan, but actually it wasn't running for long before the intermittent switch caused the trap to restart.

The original power supply with the 50 foot cord had significant voltage drop to somewhat limit the inrush current, which might have helped a bit. Your substitute power supply might be supplying significantly more current than the original, which would add to the problem.

This reminds me of using a dimmer to run incandescent lamps: when fading up the bulb, it warms up (more) slowly than a toggle switch, and the bulb lasts much longer. Perhaps you could use a PWM output to drive the FET so that the heater warms up slowly as well. I think I might try this with the NodeMCU design. Those igniters are too expensive to just consume like that, and it is a nuisance to stock and replace them.
Re: Defender Arduino Design
October 07, 2019 11:52AM
I bet the mosquito magnet people are reading your posts.
Sorry, only registered users may post in this forum.

Click here to login