Welcome! Log In Create A New Profile

Advanced

Defender Arduino Design

Posted by beads 
Re: Defender Arduino Design
October 10, 2019 03:23PM
"I bet the mosquito magnet people are reading your posts."

I don't think so. First of all, the forum and blog are relatively new. Second, the original company is long gone, and the new company is, thankfully, still in business. But we cannot assume they have the same passion as the original inventors, who could have some interest, but are now likely away from the field. Third, this is an unpublicized, low-traffic website, with these completely unrelated posts just a hobby. Only a direct search for relevant terms would lead anyone to this site. Finally, there has been no communication from anyone in an official capacity, which is a clue. So I wouldn't bet on it.
New Season: Defender Arduino Design
April 17, 2020 02:59PM
Contact form message received from Beads (originally posted to forum by dev):

Hello!

I'm getting ready to fire up the Mega Defender from last year- this will be the true test of the survivability of the Arduino Mega design. The number one complaint of the Mosquito Magnet remains a failure to light-off after year one, even after a decade of production.

I have a Defender board that I removed from one of the used Defender's I bought on Ebay, are you interested in having it? I will send to to you - no charge to you- since you put together the site that motivated me to try this hack. It is the very least I can do. If you provide an address, I'll mail it next week.

I wrote code based on your recommendation to slowly energize the igniter and hopefully remove stress and prolong the life. I think I will get one full season out of it now (about 200 light offs) - the savings in propane more than pays for one igniter per year. If I cut it to one lightoff per day, it doubles yet again.

Also on tap is incorporating a flammable gas sensor which is already on hand. I really don't have any concern about the danger of explosions...at least no more than a gas grill... but understand others and their worries. My concern would be adding a new failure mode that could cause false shutdowns. Elegant coding will be required.

One last thing- You mentioned last year about doing a separate blog page - how could that work? You already have a very detailed page; would it be easy to add a separate thread?

Thanks again for the comments and advice - the Mega Defender worked great last year.
[attachment 74 MM_Board.jpg]
Re: New Season Defender Arduino Design
April 17, 2020 04:25PM
Good to hear you getting started. Yes, seasonal restarting has been a classic Defender problem, but with mine, I had new, different issues. Last year, I hit a patch where I had all sorts of problems with starting (see the blog). One of them was the regulator, which had "worn out" or something. Another was I was using the wrong replacement nozzle. I ended up using an original nozzle thoroughly cleaned in brake cleaner. Having a telemetry log file of the combustion chamber (thermistor) temperature plus the other operating points was essential in sorting this out.

But the new reliability issues are related to weather vs the electronics. This will be more severe if the case temperature fluctuates to allow humidity, etc. to corrode the connections.

I am not sure what I would do with a spare Defender board. But these should be valuable, please hold onto it! If I think of a use, I will let you know, but perhaps another user really needs a new controller. Of course, you are not sure that it works. Using this forum, I am willing to help you or someone else troubleshoot and repair their or your controller.

Gently ramping up the current into the igniter will likely make a big difference, and keeping it on only until a noticeable temperature rise has occurred will also help. Even so, I wonder how long the igniters will last. I don't know for how much longer they will be available for purchase in the future. Are you paying a lot for propane? I remember that my propane costs are about $7 every three weeks. My only issue was a desire to add an electronic scale to the system, so I could measure and report the tank capacity, but I think I will look into gentle start as well, even though the igniter runs only rarely (e.g., after a power failure).

I don't think a flammable gas sensor inside the case would be important. More interesting would be a temp, CO2, humidity, and perhaps CO sensor on the exhaust port. That way, you could tell how well the trap is working. Also, that idea of a mosquito detector would be very cool.

Quote

... You mentioned last year about doing a separate blog page - how could that work? You already have a very detailed page; would it be easy to add a separate thread?

Was that a blog, or a wiki page? Do you want to write about your experiences? Or do you want some pages in the wiki? For a blog, your best bet is to use a free blogging provider. We can add links to the blog from the wiki, my blog, and this forum. These cross-site links are better for many reasons. If you want to do the wiki, I think I can set that up. Let me know.

BTW, you can the "private messages" feature to send personal, private messages instead of the contact form.
Re: Defender Arduino Design
May 17, 2020 12:18AM
MEGA DEFENDER REV1

It's 2020 and the new mosquito season is upon us, though the well below average temps in the mid-Atlantic have delayed the need to restart the Mega Defender until now. At the end of last year I acquired two vintage, non-working Defenders through eBay for $180, and decided to re-build an entire system. The original system from last year will go to work for a friend near the water, so that will be a true test of reliability and effectiveness.

When the old Defender case was opened on the second build, the reason it was non-working was immediately apparent: the nylon screw head that was supposed to secure the original thermistor was sheared off, and the thermistor was dangling free. Quite a bit of effort was spent prying apart the hot section to give it a good clean (it was in bad shape), then RTV was used to create a new gasket seal when screwed back together.

Based on inputs from a couple interested parties last year, there are some pretty significant changes to the last design:

1. A dimmer function was added to the igniter sequence to slowly ramp up to full power to reduce stress on the igniter over an 18 second period
2. An MQ-2 propane gas detector was added to pin A0 to measure gas levels near the valve solenoid
3. The working thermistor was wired into an analog pin on the Mega via a voltage divider
4. The Serial and Bluetooth functions were deconflicted allowing the code could to always run as is, so plugging the USB cable into a laptop provides detailed data to be seen during operation
5. The existing power switch was used instead of adding another switch on the bottom of the case


The new system fired up perfectly on the first try with propane. It took some work in the workshop running tests and the revised Arduino code to get the new functionality up and running. It is so nice having both Bluetooth and the serial monitor available on the same code, unlike last year.

The updated wiring diagram is included below, as well as updated pictures and the new code (Version 17) at the end of this post. The code is not elegant, but it is functional. 10% of language memory is used, and 27% of variable memory, as of V17. Still plenty of margin. Keep in mind to actually make the Mega Defender work, all that is actually need are two 18B20 temp sensors, three MOSFETs and the Real Time Clock (RTC) - about $30 including the Arduino Mega.



Photo and Video Album

After checking that the thermistor worked and measuring its resistance (150K Ohms),it was included in the recorded data on the SD card and wired it via voltage divider to analog Pin 1 (A01). Right now, the data is simply stored to the SD card to help with analysis, though it could potentially be used in the ignition logic. As can be seen in the initial lightoff plot below, the thermistor is much more sensitive to the temperature increase, but is much noisier as well. Since the 18B20 temp sensors are working so well, there’s no motivation to change anything.



The new MQ-2 gas sensor is also just for data- it didn’t make sense to set trip limits without first looking at the data from a week or more of operation. As mentioned in earlier posts, the danger of any propane “explosion” is virtually zero; certainly no more than a gas grill, which has no such feature.

The Pulse Width Modulation function built in to the Arduino Mega is perfect to slowly ramp up power to the igniter. The V17 setting is 75 milliseconds per increment from 0-255, which translates to about 19 seconds to full power. The valve MOSFET is triggered at about 15 seconds into the sequence, when the igniter is already glowing. It works so far- hopefully the life of the igniter will be bumped up, especially with two lightoffs per day.

It really would be great to design a system to detect mosquitoes once they are in the trap. That little Doppler radar unit is the easiest to try, but after realizing that the biters spend the whole time plastered against the screen, it may be too hard to see. Acoustics would be a potentially good way, since mosquitoes have such a distinctive high pitch whine.

As always, please provide inputs on what may be improved upon, or any other ideas related to this project. BTW- the original Mega Defender fired up perfectly first time after being stored all winter, so the primary problem with these units (no lightoff after being in storage) really does seem to be fixed.

//Mosquito Magnet Defender
//Version 17  25  April 2020
#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 gasPin A0
#define thermistorPin A1
#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 = 300;// total igiition cycle until timeout; 300 seconds works
  float lightoff = 10.1;// delta T (deg F) for ignition
  float temp = 0;
  float dTemp = 0;
  float aTemp, iTemp,a2Temp;
  unsigned long readsec,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";
  float gas_sensor, thermistor;
  
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(9600);
  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
  analogWrite(igPin, 0);// 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 V17 w/ gas sensor & thermistor");
    myFile.println("loop#,hours,dayofmonth,month,year,hour,min,sec,hours,stat,stat2,temp,amb_Temp,delta_Temp,humidiy,a2Temp,total_hrs,propane_hrs,total_days, propane_days, gas_sensor,thermistor");
    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,gas_sensor,thermistor");
    myFile.close();
  }

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

  refresh_oled(); //Show initialize screen to check temp sensors
  delay(6000);// wait 6 seconds to allow OLED screen to be read and settle gas sensor
}


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);
   
//#####################  || is "normal" between breaks ; using "&&" runs 24/7 for testing and troubleshooting
  if ((hours > 0.50 && hours < 6.0) || (hours > 9.5 && hours < 16.25)){ // sleep routine; sleeps late at night and mid day
           stat = "SLEEPING";
           start = false;
           analogWrite(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){stat = "SHUTDOWN ";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";
    Serial.println("inside ignite_cycle"); 
    
    for (int zz = 0; zz<= 255; zz++) { // start igniter slowly, about 19 seconds to max power
        analogWrite(igPin,zz); Serial.print(zz);
        if (zz > 210){ digitalWrite(valvePin, HIGH); Serial.print("   propane on");}//propane on at about 15 seconds
        delay(75);Serial.println();
      }

    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.65 && elapsed > 45) {
          analogWrite(igPin, 0);  //  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   delta Temp "); Serial.println(temp-iTemp); Serial.print("temp "); Serial.println(temp); 
        Serial.print("aTemp "); Serial.println(aTemp); Serial.print("Elapsed "); Serial.println(elapsed); 
        Serial.print("  thermistor "); Serial.println(thermistor);
    
        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.print(hours);myFile.print(","); myFile.print(gas_sensor);myFile.print(","); myFile.println(thermistor);
        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();
    }

    analogWrite(igPin,LOW); // stop igniter if still on

    if (elapsed <= start_time){
          start = true; x = 0;
          stat2 = "Good Ignition"; 
          analogWrite(fanPin, 210);// Set fan to mid-high speed
          Serial.println(stat2);oled.println(stat2); delay(1000);}
    else {start = false;
          stat = "SHUTDOWN ";
          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);
  *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(){
      digitalWrite(valvePin, LOW);//propane off
      analogWrite(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;
  gas_sensor = analogRead(gasPin);
  thermistor = analogRead(thermistorPin);
  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 ignited
            
            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(a2Temp);
            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.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.print("  Thermistor: "); Serial.println(thermistor);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(",");
        BTserial.print(gas_sensor,3);BTserial.print(";"); // last output needs to have the ";"
}



Edited 2 time(s). Last edit at 05/17/2020 12:20AM by beads.
Re: Defender Arduino Design
June 15, 2020 06:15PM
Hello - I really appreciate the work you've put into this. I have been envisioning a system very similar to the one you've built so I am happy that I stumbled upon this thread!

I've been thinking about getting rid of the propane altogether and replacing it with a CO2 canister that is run through a heated chamber. Do you guys see any challenges with this approach? I would still use an arduino to control the exhaust temperature, CO2 on/off, etc.
Re: Defender Arduino Design
June 20, 2020 06:56PM
Seems like a fairly complicated way to generate both heat and the C02...unless you have easy access to a large c02 cylinder or other large scale source. Otherwise,, that's essentially all the MM does with propane. The nice thing about the propane is how easy it is to get refills (any Wal Mart, Home Depot, etc) has Blue Rhino or Amerigas that takes minutes to swap. The power to drive the heated chamber may be significant; especially depending on how the C02 flows through - too quickly and it will take many amps of power, turning the Mosquito Magnet into a power hog.

The Arduino has been fantastic at providing very finely tuned controls, and excellent data recording to allow troubleshooting. One new issue I had this year is that I bought a couple different brand Megas on Amazon, and they don't like the 5V 10A transformer power (measured at 12.86V, slightly out of spec for the Mega). I wired in an LM7805 voltage regulator and that fixes the problem- but honestly; that was a tough one to troubleshoot.

It would be interesting to see what you come up with in the design- please keep us posted.
Re: CO2 Canister
June 22, 2020 03:22PM
HouseInTheWoods wrote:
I've been thinking about getting rid of the propane altogether and replacing it with a CO2 canister that is run through a heated chamber.

I believe that is what the original Mosquito Magnet developers did for testing before they switched to propane. I think the major reason to use propane is cost. Last year, I paid around $2.15 to 2.36 per gallon at Tractor Supply. One gallon of propane weighs about 4.23 lbs, so refilling a 20 (about 9 kg) pound tank cost around $10 (frequently there was some remaining in the tank).

From https://www.answers.com/Q/How_much_carbon_does_burning_propane_release:

The formula for the combustion of propane is:
C2H6 + 5O2 --> 2CO2 + 3H2O
So each mole of propane creates two moles of carbon dioxide.
One mole of propane is 30 g, one mole of carbon dioxide is 44 g
So each gram of propane creates (2x44)/30)= 2.93 g of carbon dioxide on combustion.
In common terms a 20lb tank of p for a BBQ creates a bit less than 60 lb of carbon dioxide


20 lb propane yielding 60lb of CO2 lasts 3 weeks, which is ~20 lb/week or ~3 lb/day.

Carbonator canisters cost somewhere between $8 to $15 per refill to provide 14.5 oz of dietary CO2. To get 60 lbs will require 66 refills, obviously too pricey, not to mention changing tanks 3 times/day.

I don't know how much it costs you to purchase 20 lb or 50 lb industrial CO2 refills, but using a 20 lb tank means changing the tank once per week. A larger tank might be a pain to handle, which is a deal killer for me. I need that trap to just run. Every three weeks propane and octenol, I can accept.

(One beer maker wrote in 2012 of $1.25/lb for a 20 lb refill. 60 lbs would have cost $75 then, which was still very high. Again, this would be food grade. On the other hand, perhaps I have made a mistake or several, and the costs are much less.)

Besides cost, there is the issue of accurately regulating the very low flow rate to 3 lb/day, and then accurately heating the cool mixture to the breath temperature. Then, what about the lack of water vapor? I forgot if that is important.

This sounds like a lot of work, which means this project is perfect for this site! (BTW, please start a new topic for your project, as this topic is for the Arduino designs.)



Edited 1 time(s). Last edit at 06/22/2020 03:57PM by dev.
Re: Defender Arduino Design
June 22, 2020 04:23PM
Great thread! Thanks for a very interesting enjoyable read.

I stay in the West of Scotland, and mosquito magnets here are aimed at the Scottish Midge - millions of tiny little flying insects who bite voraciously throughout the Spring and Summer. (think you might know them as no-see-ums?)

Anyway, the magnet (Patriot plus) is brilliant for clearing them out and give us (and our neighbours) gardens back.

Have faced all the usual issues with the magnet and just finished stripping it down and cleaning it (nozzle filter basket blocked). It wasn't easy what with the lack of error codes and I now finally know how it works having read all the useful information here.

The Arduino is a great idea and all the bits seem to be cheap and readily available. Particularly interested in saving gas through only having it on while they're flying (propane here comes in 13kg bottles at a cost of around 40$ for a refill)

Wondered if you'd thought about weighing the gas cylinder via a pressure sensor like this one https://www.amazon.co.uk/dp/B082LS9L35/?coliid=I3K63XGTY25IW4&colid=K8XL1E6VNP17&psc=1&ref_=lv_ov_lig_dp_it

You'd have to reset on cylinder change, then have it measure a reduction of the amount of gas weight. Might try this..

Also - I see on the original schematic that there are 3 wires coming from the fan - is one of them a tacho? Do you use this for fan speed?

Can see this being a great Autumn project!



Edited 1 time(s). Last edit at 06/22/2020 04:24PM by Midge.
Re: Mega Defender Rev1
June 22, 2020 04:35PM
beads: I read your post of 5/17/2020 with great interest. Your project sounds like a great success. Good luck with it as you engineer it for greater robustness as we head into the summer. I started my trap at the end on May, but it started catching mosquitos only last week. June has been quite dry here.

When the propane ran out, I switched the catch baskets, and there were about 275 mosquitos, plus about 30-50 times that of tiny flies ("no-see ums") which were all I caught in the first 2 weeks of operation, now sort of all stuck together by something. Just an awful mess.

I noticed that my trap was not running, and restarted it, twice, but it would not start. The tank was empty. With a full tank, it still would not start, and there was no temperature rise whatsoever during the igniter on interval. Sure enough, removing the igniter and restarting, it failed to glow. I installed a new igniter, which did glow, and the trap started. I will write a blog post with more information.

Do you have any igniter life information from before and after you made your mod to slowly ramp up the inrush current? Has it made any difference? My trap is always on (propane is $10 a tank here), and I don't have the number of cycles and hours on the possibly failed igniter (it might be ok, and a connection might have been poor). I would like to get a handle on igniter reliability. How many cycles have you gotten from each igniter so far, and how many since you started limiting the inrush current?

On another matter, I would like to see your 5/27 post on the wiki, along with the photos, so that everything is all in one place, and so you and others can edit it in place. Are you interested in having this happen?
Re: Defender Arduino Design
June 25, 2020 01:55PM
This is amazing stuff.
Propane Cost
June 25, 2020 06:40PM
Propane has gone up a bit. Today I paid $2.69 / gallon. Refilling an empty 20 lb tank took 4.45 gallons and cost $11.97.
Re: Propane Cost
June 30, 2020 02:20AM
To answer the igniter question- since going with the dimmer function (PWM), I haven't had any issues at all with the igniter. In fact, in the rebuilt Defender I am currently running in my backyard I tested and used the original igniter that is at least 8 years old, and it has been lighting twice a day for 6 weeks at least. The igniter last year must have worked at least 120 times- a far cry from the original Defender that I was hopeful to get four or five light-offs in a season.

To answer another question- the third wire from the fan is the tachometer, but I chose not to use that input in the Arduino logic. I was getting spurious tach readings when I tried to hook it up when the fan was running fine, which would have caused an erroneous shutdown. The fan is clearly audible, so I consider that the primary method for monitoring, though I suppose that if the fan fails (pretty low failure rate), the Magnet could overheat- or maybe not.

I cleaned out the Mega Defender tonight- it only had about 50-60 mosquitoes after seven days, though because I have been running a Defender in my backyard for more than a decade, it is likely the number I'll get will never reach the levels of the first year. We hardly ever see mosquitoes in our wooded backyard anymore, so the Mega Defender is really doing its job.

The first propane tank lasted 35 days, way way longer than the the turn it on and run it dry method. The total run and propane hours are plotted below. I have to pay attention to the attractant life, and just recently bought a small bottle of Octenal on eBay to "refresh" those much more affordably than buying the packs of three. Does anyone know why Lurex sales were halted?



The thermistor is way more sensitive than the Arduino temp sensor that is mounted on the heat sink fans. In the plot below the thermistor output was scaled to match the two temp sensors. In this latest build, the Arduino hot temp sensor is mounted flush to the metal, so it measures much higher temps than the original install. Below is the file that tracks the ignition cycles for each of the 14 or so lightoffs; the morning and afternoon temps are clear as it does two lightoffs per day.



I had a couple small problems with the Defender at the beginning of the season. We had very heavy rains a couple times, and somehow a drop of water got onto the connector of the micro SD card reader mounted on the bottom; of course it hit right between the Vcc and ground pins, causing a short and making the Arduino Mega unhappy. It was a quick fix, but the blog Dev host was right that the design- at least my build- is not very robust for weather, though it did run all last season, and fired up first try this year. The other issue was plain clumsiness on my part: when mowing the lawn the mower handle hit the OLED display and caused about a third of it to go blank. When I swapped tanks, I swapped the display and it was fine.
Re: Defender Arduino Design
July 01, 2020 10:15AM
Are there any issues with the MOSFET getting warm during the PWM phase?

Also, I was wondering about your 12V 10A supply - does that replace the original psu and then feeds the 50' cable, or is it an external unit nearer the Defender?

When the igniter is on, is there much of a voltage drop across it? I think you said earlier it draws just over 3A?
Re: Defender Arduino Design
July 03, 2020 12:19AM
Since going to the "monster" MOSFETs, they don't get warm at all. I bought them on Amazon:

55v 110A MOSFET


The power supply (also on Amazon) is key. When I did a "buy it again" for the next build Amazon sent a smaller 5A version, which seems to have trouble during the ignition cycle with the fan, igniter and valve all being powered along with the Mega. Everything worked great when replaced with the 10A correct model. I think the peak current I saw from the igniter was 3.6A using the workbench digital power supply. No measurement was made of the voltage drop while connected to the external supply- but I can try to check that this weekend. The original mosquito magnet power supply is completely removed. In fact, the hole left by removing the original power adapter is used to install the ambient Dallas temp sensor and the DHT11 temp/humidity sensor. An extension cord is used to get the power far enough out the Mega Defender with no issues, at least yet.

One thing that seems to help is that the old attractants are placed on the ground below the Mega intake, since they don't just go to zero at 25 days or so; not sure how much impact it has, but it can't hurt.

UPDATED PHOTOS

An issue that is part of the code is that the OLED display doesn't work when there is no micro SD card installed. The SD cards are super cheap and don't need to be large (8mB is way more than a couple tanks worth of data).

Softserial was used originally for Buetooth, but since the code was written I have gained more experience with the Arduino hard serial ports, and would change to that if it didn't work already. The HC-05 Bluetooth modules from Amazon are not too robust- they seem to stop working after a couple months of continuous power on.

I had every intent on making a short video for YouTube that showed the general build and described the Arduino approach, with links to this forum. Instead, I built a seven channel Arduino Mega/Bluetooth fireworks controller for this weekend that is pretty cool (that's how I learned about hard serial Bluetooth usage).



Edited 2 time(s). Last edit at 07/03/2020 11:22AM by beads.
Re: MOSFET getting warm
July 03, 2020 09:33PM
Are there any issues with the MOSFET getting warm during the PWM phase?

There shouldn't be any problem with even the original mid-spec MOSFET as long as the drive is sufficient to completely turn on the device, which it is. The original defender MOSFET with the NodeMCU add-on is being driven by 3.3 volts instead of the original 5 volts, and still turns on hard with no heating. PWM switches the MOSFET hard on and off. Another way to do a soft start is to make the MOSFET a variable current source (i.e. linear or saturation mode), which would dissipate a lot of power as the power ramps up. Although it might be gentler on the igniter, the heat sinking and perhaps the device itself on the Defender board might be insufficient for that mode, so it is not practical without a lot of extra effort. See the blog for a further discussion.
Re: Defender Arduino Design
September 13, 2020 08:34PM
The 2020 mosquito season is wrapping up. There have been three Mega Defenders running now nearly continuously for two months, so six light-offs per day, almost without issues. Almost, because I have had two of the 12 V power supplies fail, entirely due to water incursion. We have had an extremely wet summer, with very heavy rainfalls. Those Amazon power supplies don’t come water-proofed. To mitigate, I now seal the two end wires with hot glue (all the way around both end wires/connections), and apply good quality electrical tape around the perimeter. So far, that’s working. By the way, I've used zero CO2 cartridges this year, and still get perfectly reliable light-offs. The chart below shows 58 light-offs, a decade's worth using the "normal" continuous-on system.




Several updates have been included in the latest posted-below software, which is release 20. The most significant is that the code now detects a brief power interruption, which has happened a couple times with afternoon thunderstorms; check out the running days total in the plot below. The old code would immediately go through the normal start-up with power restored, and in the first pass at the ignition loop see the hot section temperature sensor was well above ambient, which made it think there was a good light off and secure the igniter and move into the normal Trapping mode, eventually leading to shutdown when it thought propane was empty as it cooled. The new code checks to see if there is an eight degree or more differential between the hot section and ambient sensor; if so, it stays in the “while” loop with the fan at max until the differential (dTemp variable) drops below eight, but no more than 15 minutes. The second plot show a test run I made where I was specifically looking to see how fast the hot section cools when propane was secured.



Another added feature is that in the initialization phase the code now checks for a failed temp sensor. It isn’t perfect, but I have found the sensors typically fail due to the crummy jumper wire connections, and give readings like -999 or 999. If the one of the temp sensors fail (it happened once out of three Mega Defenders after months of running), the code sends it into shutdown or it won’t relight after going to sleep.



As I ungracefully age, my reading vision is getting worse, so I modified the OLED output commands so I don’t need reading glasses to see those tiny display characters. Every 2.5 seconds or so, the data alternates between temps and total time and propane time and RTC clock time. The Bluetooth modules burn out after a few weeks, it seems the cheap Amazon versions used are not designed to run 24/7 for months, which Is believable.

I have had ZERO issue with the igniters’ since going to the slow warm up mode using PWM at the beginning of the season. That’s hundreds of light-offs just this season alone, I’m going to call it and say that problem is solved.

The Mega Defenders have been catching a much higher number of mosquitos his year compared to previous years. The really wet summer is probably the main reason- all my neighbors are complaining about how bad the biters are this year. Until it suddenly cooled off outside recently, there were 30-40 biters in the trap each day, more than double or even triple last year. The deck is livable, so it is working.

The V20 code below could definitely be streamlined, but it works really well. Others are encouraged to revise and post updates.

//   Mega Defender Mosquito Magnet 
//Version 20 12 Sept 2020
#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 gasPin A0
#define thermistorPin A1
#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

  String rev = "20"; // Version number

  bool start = false, disp = true;
  float chk; 
  int cool_time = 0;
  float start_time = 310;// total igiition cycle until timeout; ~300 seconds works
  float lightoff = 8.1;// delta T (deg F) for ignition
  float temp = 0;
  float dTemp = 0;
  float aTemp, iTemp, a2Temp, cTemp;
  unsigned long readsec,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";
  float gas_sensor, thermistor;
  
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(9600);
  BTserial.begin(9600);
  initTime = millis()/1000;
    
  pinMode(fanPin, OUTPUT);pinMode(igPin, OUTPUT);pinMode(valvePin, OUTPUT);

    digitalWrite(valvePin, LOW);//propane off
    analogWrite(fanPin, 170);// Set fan to mid speed; range is 0-255
    analogWrite(igPin, 0);// igniters off until called
  
  sensors.begin(); 
  //delay(2000);
  get_temps();

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


  Serial.println("Mosquito Magnet Mega Defender V" + rev);
  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.");
  oled.clear(); oled.set2X(); oled.println("SD CARD OK"); oled.print(" REV " + rev);oled.set1X();
    myFile = SD.open("Magnet.txt", FILE_WRITE);   // if the file opened, write to it:
  if (myFile) {
    myFile.println("Mosquito Magnet Mega Defender V" + rev);
    myFile.println("loop#,hours,dayofmonth,month,year,hour,min,sec,hours,time,date,stat,stat2,temp,amb_Temp,delta_Temp,humidiy,a2Temp,total_hrs,propane_hrs,total_days, propane_days, gas_sensor,thermistor");
    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,gas_sensor,thermistor");
    myFile.close();
  }
  get_temps();
  readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  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();
  iMinute = minute;
  
  refresh_oled(); //Show initialize screen to check temp sensors
 
  delay(1500);// wait  to allow OLED screen to be read and settle gas sensor
  
//###  Detect short power interupt, hot section still warm
   if (dTemp > 100 || dTemp < -5) { // check for a temp sensor failure
     stat = "TEMP FAIL";
     shut_down;
   }
  int cool_minute;
  cool_minute = iMinute;\
  
while (dTemp>8 && cool_time < 16){// run fan, cool down until hot temp is within 8 degs or 16 minutes has passed
  stat = "POWER LOSS";
  analogWrite(fanPin, 255);// Set fan to max speed; range is 0-255
  readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  refresh_oled;
      if (cool_minute != minute){cool_time ++; cool_minute = minute;}
  file_write(); serial_write(); refresh_oled();bluetooth();
}
  file_write(); serial_write(); refresh_oled();bluetooth();
}

void loop(){
   get_temps();
   readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
   iMinute = minute;
   dec_min = minute; dec_hour = hour;    
   hours = dec_hour + (dec_min/60);
   
//#####################  || is "normal" between breaks ; using "&&" runs 24/7 for testing and troubleshooting
  if ((hours > 0.25 && hours < 6.25) || (hours > 9.75 && hours < 16.00)){ // sleep routine; sleeps late at night and mid day
           stat = "SLEEPING";
           start = false;
           digitalWrite(valvePin, LOW);//propane off
           analogWrite(fanPin, 230);// Set fan to mid-high speed
   }
           
   else {  // trapping routine
       
       if (!start){ignite_cycle();} // runs igition if this is the first loop pass the start time 
       stat = "TRAPPING";

       if (dTemp < lightoff -1){stat = "SHUTDOWN ";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 = "WARM UP ";
    Serial.println("inside ignite_cycle"); 
    analogWrite(fanPin, 160);// Set fan to mid-low speed for ignition; range is 0-255
    refresh_oled();
    
    for (int zz = 0; zz<= 255; zz++) { // start igniter slowly, about 19 seconds to max power
        analogWrite(igPin,zz); Serial.print(zz);
        if (zz > 210){ digitalWrite(valvePin, HIGH); Serial.print("   propane on");}//propane on at about 15 seconds
        delay(75);Serial.println();
      }
    stat = "POST IGN"; 
    initTime = millis()/1000;
    get_temps();
    iTemp = temp;
    stat2 = "igniter on";
    refresh_oled();
    Serial.println("  POST IGNITER ");delay(1500);
    
    while (elapsed <= start_time && dTemp < lightoff) {
        x++; stat= "IGNITION";    
        iMinute = minute;
        readsec = millis()/1000;
        elapsed = (readsec - initTime); // provides run time
        get_temps();
        readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
        Serial.print("  x= "); Serial.println(x);
        if ((temp-iTemp) > 1.65 && elapsed > 55) {
          analogWrite(igPin, 0);  //  turn off igniter, stay in ignition monitoring loop til start_time or lightoff temp is reached         
          analogWrite(fanPin, 225);// Set fan to mid-high speed
          stat2 = "igniter off";
        }
        
        Serial.print("IGNITION   delta Temp "); Serial.println(temp-iTemp); Serial.print("temp "); Serial.println(temp); 
        Serial.print("aTemp "); Serial.println(aTemp); Serial.print("Elapsed "); Serial.println(elapsed); 
        Serial.print("  gas sensor "); Serial.println(gas_sensor);
        Serial.print("  thermistor "); Serial.println(thermistor);
    
        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(temp-iTemp);
        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.print(hours);myFile.print(","); myFile.print(gas_sensor);myFile.print(","); myFile.println(thermistor);
        myFile.close(); 

        file_write();
        
          oled.clear(); oled.set2X();
          oled.println(stat); oled.set1X();oled.println();
          oled.print(temp); oled.print("    ");oled.println(temp-iTemp);
          oled.print("temp"); oled.println("   Temp rise"); oled.println();
          oled.print(" Ignition time: "); oled.println(elapsed); 
          oled.print(stat2);oled.println("   ");
          
          bluetooth();
    }

    analogWrite(igPin,0); // stop igniter if still on

    if (elapsed > start_time || dTemp < lightoff){
          start = false;
          stat = "SHUTDOWN ";
          stat2 = "No Ignition"; Serial.println(stat2);oled.println(stat2);
          shut_down(); }
          
    else {start = true; x = 0; // good lightoff
          stat2 = "Good Ignition"; 
          analogWrite(fanPin, 240);// Set fan to mid-high speed
          Serial.println("Ignition cyle complete.  Good lightofff");oled.println(stat2); delay(1000);}
}

 // 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);
  *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(){
      digitalWrite(valvePin, LOW);//propane off
      analogWrite(igPin, 0);//be sure ignition is off
      analogWrite(fanPin, 215);// Set fan
      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 temp
  aTemp = sensors.getTempFByIndex(0);// Ambient location 
  cTemp = sensors.getTempFByIndex(2);// 3rd location temp
  dTemp = temp - aTemp;
  chk = DHT.read11(amb_temp);
  a2Temp = DHT.temperature*1.8+32;
  gas_sensor = analogRead(gasPin);
  thermistor = analogRead(thermistorPin);
  delay(1600);
  
}  

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 ignited
            
            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(hour); myFile.print(":"); if (minute < 10){myFile.print("0");} myFile.print(minute); myFile.print(",");
                 myFile.print(month); myFile.print("/"); myFile.print(dayOfMonth); myFile.print("/");myFile.print(year); 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(a2Temp);
            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.print(",");myFile.print(gas_sensor);myFile.print(","); myFile.println(thermistor);myFile.close(); 
       }
}

void refresh_oled(){ //Push data to the OLED display
     oled.clear(); oled.set2X();
     if (disp){
         oled.println(stat);//oled.set1X();
        oled.print(temp,1); oled.print(" ");oled.println(aTemp,1);//oled.print("  ");oled.println(DHT.humidity);
        //oled.println(" temp   ambt   humid.");
        oled.print("Days: ");oled.println(total_days,1);
        disp = false;
     }
      else {  
        oled.println(stat);
        oled.print("P_days:");oled.println(propane_days,1);
        oled.print("Time:");oled.print(hour, DEC); oled.print(":"); oled.println(minute, DEC); 
        disp = true;
      }
}
        
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("Time: ");Serial.print(hours); Serial.print("  run hrs ");Serial.println(total_hours,3);Serial.print("  Thermistor: "); Serial.println(thermistor);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(",");
        BTserial.print(gas_sensor,3);BTserial.print(";"); // last output needs to have the ";"
}


Re: Three Mega Defenders
September 14, 2020 04:20PM
Sounds like you have had a great summer!

...the code now detects a brief power interruption...

Right. FYI, The NodeMCU starts the fan for 30 seconds to clear out any propane, then, if necessary, to cool the unit to the low thermistor temperature fault limit (configured to 70°C) before entering the ignition/gas state. This is done because the igniter remains on only until the temperature rises 5°C or 3 minutes have passed, and not longer. At that temperature, the 5°C temperature rise occurs after about 1 minute. The cool down takes only a few minutes, so for me, the simplicity is worth the short time the trap is not producing CO2. The mosquitos will just have to wait, and they do.

...sensors typically fail due to the crummy jumper wire connections...

What's happening? Is it corroding? Is it the connection on the sensor PCB, or at the breadboard? I have an HTU-21D with cheap 100mil connectors hanging in the air intake before the catch basket, where it measures temperature and humidity, and so far so good. Perhaps a protective coating of DeOxit or similar might help.

The Bluetooth modules burn out after a few weeks...

That should not happen. Bluetooth modules are (or should be) designed exactly to run 24/7 for years and years. Perhaps something else is zapping them, a power supply transient? You could try switching to a $4 NodeMCU module (e.g., Wemos D1 mini) programmed as a serial to WiFi telnet and/or MQTT repeater.

...ZERO issue with the igniters...problem is solved.

I think you have proven that, especially with that stiff (non-sagging) power supply, which would be more or less the acid test.
Re: Defender Arduino Design
November 01, 2020 05:38PM
The four Mega defenders have been put into semi-warm storage (basement and garage) for the winter. The two I keep up and running in my yard did a very good job knocking back the swarms, in what was a very bad year for mosquitoes in northern Virginia.

The very latest code is below, which includes the power outage logic that worked great. I also doubled the font size for temperature and "time on" data on the small OLED display, since my near vision is fading as I become an old fart.



A couple short videos were added to the Mega Defender album (sorry- they were placed out of order)

Another issue this year that really kicked my butt was the water intrusion in the power supplies. Those $19 12V DC units were definitely not engineered to be left outdoors in the rain. Three of the supplies died (two in the same rain storm), so the answer was to hot glue and seal the ends with the wires and tape around the perimeter (see pic). There were zero failures after sealing the power supplies.



These defenders are workhorses once the crummy logic has been replaced! A fresh propane tank lasts right around 40 days, so I ended up buying bulk octenol from some guy in the Ukraine to "recharge" the regular units. A couple drops were added every week or so- it made a difference in the number of biters trapped.

Good hunting!

//   Mega Defender Mosquito Magnet 
//Version 20  4 Oct 2020
#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 gasPin A0
#define thermistorPin A1
#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, disp = true;
  String rev = "20"; // Version number
  float chk; 
  int cool_time = 0;
  float start_time = 310;// total igiition cycle until timeout; ~300 seconds works
  float lightoff = 8.1;// delta T (deg F) for ignition
  float temp = 0;
  float dTemp = 0;
  float aTemp, iTemp, a2Temp, cTemp;
  unsigned long readsec,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";
  float gas_sensor, thermistor;
  
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(9600);
  BTserial.begin(9600);
  initTime = millis()/1000;
    
  pinMode(fanPin, OUTPUT);pinMode(igPin, OUTPUT);pinMode(valvePin, OUTPUT);

    digitalWrite(valvePin, LOW);//propane off
    analogWrite(fanPin, 170);// Set fan to mid speed; range is 0-255
    analogWrite(igPin, 0);// igniters off until called
  
  sensors.begin(); 
  //delay(2000);
  get_temps();

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


  Serial.println("Mosquito Magnet Mega Defender V" + rev);
  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.");
  oled.clear(); oled.set2X(); oled.println("SD CARD OK"); oled.print(" REV " + rev);oled.set1X();
    myFile = SD.open("Magnet.txt", FILE_WRITE);   // if the file opened, write to it:
  if (myFile) {
    myFile.println("Mosquito Magnet Mega Defender V" + rev);
    myFile.println("loop#,hours,dayofmonth,month,year,hour,min,sec,hours,time,date,stat,stat2,temp,amb_Temp,delta_Temp,humidiy,a2Temp,total_hrs,propane_hrs,total_days, propane_days, gas_sensor,thermistor");
    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,gas_sensor,thermistor");
    myFile.close();
  }
  get_temps();
  readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  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();
  iMinute = minute;
  
  refresh_oled(); //Show initialize screen to check temp sensors
 
  delay(1500);// wait  to allow OLED screen to be read and settle gas sensor
  
//###  Detect short power interupt, hot section still warm
   if (dTemp > 100 || dTemp < -5) { // check for a temp sensor failure
     stat = "TEMP FAIL";
     shut_down;
   }
  int cool_minute;
  cool_minute = iMinute;
while (dTemp>8 && cool_time < 16){// run fan, cool down until hot temp is within 8 degs or 16 minutes has passed
  stat = "POWER LOSS";
  analogWrite(fanPin, 255);// Set fan to max speed; range is 0-255
  readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  refresh_oled;
      if (cool_minute != minute){cool_time ++; cool_minute = minute;}
  file_write(); serial_write(); refresh_oled();bluetooth();
}
  file_write(); serial_write(); refresh_oled();bluetooth();
}

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);
   
//#####################  || is "normal" between breaks ; using "&&" runs 24/7 for testing and troubleshooting
  if ((hours > 0.25 && hours < 6.25) || (hours > 9.75 && hours < 16.00)){ // sleep routine; sleeps late at night and mid day
           stat = "SLEEPING";
           start = false;
           digitalWrite(valvePin, LOW);//propane off
           analogWrite(fanPin, 230);// Set fan to mid-high speed
   }
           
   else {  // trapping routine
       
       if (!start){ignite_cycle();} // runs igition if this is the first loop pass the start time 
       stat = "TRAPPING";

       if (dTemp < lightoff -1){stat = "SHUTDOWN ";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 = "WARM UP ";
    Serial.println("inside ignite_cycle"); 
    analogWrite(fanPin, 160);// Set fan to mid-low speed for ignition; range is 0-255
    refresh_oled();
    
    for (int zz = 0; zz<= 255; zz++) { // start igniter slowly, about 19 seconds to max power
        analogWrite(igPin,zz); Serial.print(zz);
        if (zz > 210){ digitalWrite(valvePin, HIGH); Serial.print("   propane on");}//propane on at about 15 seconds
        delay(75);Serial.println();
      }
    stat = "POST IGN"; 
    initTime = millis()/1000;
    get_temps();
    iTemp = temp;
    stat2 = "igniter on";
    refresh_oled();
    Serial.println("  POST IGNITER ");delay(1500);
    
    while (elapsed <= start_time && dTemp < lightoff) {
        x++; stat= "IGNITION";    
        iMinute = minute;
        readsec = millis()/1000;
        elapsed = (readsec - initTime); // provides run time
        get_temps();
        readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
        Serial.print("  x= "); Serial.println(x);
        if ((temp-iTemp) > 1.65 && elapsed > 55) {
          analogWrite(igPin, 0);  //  turn off igniter, stay in ignition monitoring loop til start_time or lightoff temp is reached         
          analogWrite(fanPin, 225);// Set fan to mid-high speed
          stat2 = "igniter off";
        }
        
        Serial.print("IGNITION   delta Temp "); Serial.println(temp-iTemp); Serial.print("temp "); Serial.println(temp); 
        Serial.print("aTemp "); Serial.println(aTemp); Serial.print("Elapsed "); Serial.println(elapsed); 
        Serial.print("  gas sensor "); Serial.println(gas_sensor);
        Serial.print("  thermistor "); Serial.println(thermistor);
    
        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(temp-iTemp);
        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.print(hours);myFile.print(","); myFile.print(gas_sensor);myFile.print(","); myFile.println(thermistor);
        myFile.close(); 

        file_write();
        
          oled.clear(); oled.set2X();
          oled.println(stat); oled.set1X();oled.println();
          oled.print(temp); oled.print("    ");oled.println(temp-iTemp);
          oled.print("temp"); oled.println("   Temp rise"); oled.println();
          oled.print(" Ignition time: "); oled.println(elapsed); 
          oled.print(stat2);oled.println("   ");
          
          bluetooth();
    }

    analogWrite(igPin,0); // stop igniter if still on

    if (elapsed > start_time || dTemp < lightoff){
          start = false;
          stat = "SHUTDOWN ";
          stat2 = "No Ignition"; Serial.println(stat2);oled.println(stat2);
          shut_down(); }
          
    else {start = true; x = 0; // good lightoff
          stat2 = "Good Ignition"; 
          analogWrite(fanPin, 240);// Set fan to mid-high speed
          Serial.println("Ignition cyle complete.  Good lightofff");oled.println(stat2); delay(1000);}
}

 // 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);
  *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(){
      digitalWrite(valvePin, LOW);//propane off
      analogWrite(igPin, 0);//be sure ignition is off
      analogWrite(fanPin, 215);// Set fan
      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 temp
  aTemp = sensors.getTempFByIndex(0);// Ambient location 
  cTemp = sensors.getTempFByIndex(2);// 3rd location temp
  dTemp = temp - aTemp;
  chk = DHT.read11(amb_temp);
  a2Temp = DHT.temperature*1.8+32;
  gas_sensor = analogRead(gasPin);
  thermistor = analogRead(thermistorPin);
  delay(1600);
  
}  

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 ignited
            
            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(hour); myFile.print(":"); if (minute < 10){myFile.print("0");} myFile.print(minute); myFile.print(",");
                 myFile.print(month); myFile.print("/"); myFile.print(dayOfMonth); myFile.print("/");myFile.print(year); 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(a2Temp);
            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.print(",");myFile.print(gas_sensor);myFile.print(","); myFile.println(thermistor);myFile.close(); 
       }
}

void refresh_oled(){ //Push data to the OLED display
     oled.clear(); oled.set2X();
     if (disp){
         oled.println(stat);//oled.set1X();
        oled.print(temp,1); oled.print(" ");oled.println(aTemp,1);//oled.print("  ");oled.println(DHT.humidity);
        //oled.println(" temp   ambt   humid.");
        oled.print("Days: ");oled.println(total_days,2);
        disp = false;
     }
      else {  
        oled.println(stat);
        oled.print("P_days:");oled.println(propane_days,2);
        oled.print("Time:");oled.print(hour, DEC); oled.print(":"); oled.println(minute, DEC); 
        disp = true;
      }
}
        
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("Time: ");Serial.print(hours); Serial.print("  run hrs ");Serial.println(total_hours,3);Serial.print("  Thermistor: "); Serial.println(thermistor);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(",");
        BTserial.print(gas_sensor,3);BTserial.print(";"); // last output needs to have the ";"
}

Re: Defender Arduino Design
April 17, 2021 05:27AM
Thank you so much for posting all of these details.

They were incredibly helpful and they really pushed me over the edge to tackling this project on my own.

I went ahead and made the same modifications to my mosquito magnet (ripped out the old controller completely).

I went with the "lite" version that omits the bluetooth, OLED, SD card, original thermistor, and gas sensors.

Additionally I used an ESP8266 for my microcontroller instead.

I adapted your code to the ESP8266 and just now got it fired up and running.

Since this unit is wifi equipped I should be able to grab all of the same stats but inject them into grafana for viewing instead.

Stay tuned, I'll post the code in a separate thread soon.
Re: Defender ESP8266 Design
April 20, 2021 11:44PM
Good work! So you built an entirely new controller, with power supply, FETs, etc? Wow!

For those who cannot or don't want to make their own controller boards, the add-on board solution might be appropriate. I will try to publish that in the NodeMCU thread or on the wiki in the near future. You all might think of adapting the Arduino and ESP8266 designs to an add-on board, as well.

A separate thread is a good idea, e.g., "Defender ESP8266 Design" or so. Keep us posted!
Re: Defender Arduino Design
April 25, 2021 06:27AM
Just picked up a pair of used Mosquito Magnets (a Liberty and a Defender) and I stumbled on this thread while trying to troubleshoot them and I was curious about a couple things:
Is there a specific reason you used an Arduino mega instead of an Uno or Mini?
As far as I can tell, all of the components besides the motherboards of my 2 magnets are essentially identical, so in my head, the Liberty should work exactly the same, just in a different case. Is that accurate, or are there details I am missing?
Liberty vs Defender
April 25, 2021 03:14PM
Quote

... As far as I can tell, all of the components besides the motherboards of my 2 magnets are essentially identical, so in my head, the Liberty should work exactly the same, just in a different case. Is that accurate, or are there details I am missing?

The Liberty has additional circuitry to monitor the performance of various components, and shut down the trap if any of these fault. The Defender just shuts down if the combustion chamber temperature goes too low (or too high), which seems to be sufficient. The Defender also has a mechanical power switch that maintains state over a power failure, a real improvement over the Liberty's pushbuttons. The Liberty did support many different failure codes, which turned out to be not so helpful to the owner given the lack of documentation and DIY repair support.

There was a lot of engineering work in the MM controller boards, but not quite enough to insure reliable operation through the years. That plus the lack of diagnostics forced a few motivated individuals to make their own controller or controller add-on. (I choose add-on because it was quicker, cheaper, easier, and likely more reliable than a whole new design, and to provide for downgrading back to the original design. You can read about some of the reliability problems on this forum. However, fixing your design in the rain with biting mosquitos hovering is just part of the fun!)

Here are some resources: Mosquito Magnet Liberty and Defender. Older devices have their own issues, you can read about that in the Defender wiki, whose dated entries were continued in the blog. For a somewhat lazy man's Defender add-on example, which is adaptable to the Liberty, see MM Defender IOT Controller and its Construction Details companion, although these have to do with a different, cheaper device (but that has built in WiFi!). One user here used a even smaller D1 Mini NodeMcu Lua WiFi board, to which I will also migrate.

Besides those resources, there are several different controllers documented in threads on this forum and on the wiki that may meet your requirements. Also, I have a project to release the latest NodeMCU version of the Defender, and Liberty controller adaptation, ideally with a power state memory improvement.
Re: Liberty vs Defender
April 26, 2021 04:36PM
Thanks for the detailed reply! I realize I should have explained myself better, though. I was thinking about converting one or both to arduino like beads did, and when I said the components appeared to be the same, I was referring to the non-motherboard parts like ignitor, thermistor, and gas solenoid. My assumption is that converting the Liberty to arduino control would be identical, but I wanted to make sure before I spent a lot of time and money tearing my Liberty apart, replacing the motherboard with an arduino, only to find out they aren't actually identical
Re: Defender Arduino Design
April 29, 2021 12:21AM
I chose the Mega because I wasn't sure how many peripherals would be added, and the size of the code when this all started. Plus, I had a few Megas laying around from another project. I nixed the automatic adjustments for daily changes in sunrise and sunset as extraneous, since the runs times were just a wag anyway, which shortened the code. The trimmed version (no Bluetooth, etc) may very well fit on an Uno.

Also, given the cost of propane and attractant each year, the cost delta between the Uno and Mega is trivial.

I plan on firing up the Mega Defenders (this will be the third season) in a few weeks. Last year far fewer changes to the code and sensors were needed. Looking back, using the thermister to detect light offs- assuming it was still functional- would have been the best way to go, since its location in the flame path makes it very quick to respond to lightoff.

Honestly, with stable code and better waterproofing, the Mega Defender seems to be pretty much "fire and forget." There really isn't a need to have all the real-time data displayed on the OLED or via Bluetooth. My original-original plan was to use couple LEDs to indicate status, but there were so many tricks with lightoff times, fan speeds, ignition sequence, etc during development that all the displayed and recorded data was helpful in troubleshooting and refining the code.

Please post any efforts with other boards or changes to the design. Since Defenders are now a very rare breed, the Liberty would be the next choice for mods if needed.

Good hunting!
Re: Defender Arduino Design
May 31, 2021 12:27PM
The first version of the Mega Defender was pulled out of the basement last weekend. With zero maintenance (did not open it up), I uploaded version 20A of the Arduino software which included slightly earlier start times and very slightly changed OLED display outputs, and plugged it in outdoors.

To my great satisfaction, the Mega Defender fired up right away! After a week of operating, I shut it down by shutting off propane- that feature works great- and the data was downloaded just to see how it was going. In a week, there were maybe a half dozen mosquitoes in the trap, but a ton of no-see-ums. The local temps have dropped to 20 deg below normal for nearly a week, so no activity is expected.

This morning- after the heaviest rainfall we've had in years, the OLED display is wonky- it is flashing- but gibberish. The seem to be water inside, which may be because the Mega Defender is set up less than a foot from the deck and below deck level; a lot of splash occurs.

Of note, I hove not used a single CO2 cartridge since 2019. I never understood the purpose of the cartridges, and they didn't seem to really help prior to switching to the Arduino controller. If anyone has a solid understanding of exactly what the CO2 flushing process achieves, it would be interesting to know. There have been hundreds of lightoffs without any CO2 used, and a dozen or so propane tanks amongst the four Mega Defenders that have been modified.

I plan on making a short YouTube video on this project- but it seems like a lot of work. Since the manufacturers of the Mosquito Magnet aren't interested in the mods (after a couple phone calls), it is best to leave it to the motivated DIYers to get to the fixes.

The latest code is pasted below.

If anyone else out there ha tried similar approaches, it would be great to hear from them!

Happy Hunting!


//   Mega Defender Mosquito Magnet 
//Version 20A  12 May 2021
#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 gasPin A0
#define thermistorPin A1
#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, disp = true;
  String rev = "20A"; // Version number
  float chk; 
  int cool_time = 0;
  float start_time = 310;// total igiition cycle until timeout; ~300 seconds works
  float lightoff = 8.1;// delta T (deg F) for ignition
  float temp = 0;
  float dTemp = 0;
  float aTemp, iTemp, a2Temp, cTemp;
  unsigned long readsec,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";
  float gas_sensor, thermistor;
  
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(9600);
  BTserial.begin(9600);
  initTime = millis()/1000;
    
  pinMode(fanPin, OUTPUT);pinMode(igPin, OUTPUT);pinMode(valvePin, OUTPUT);

    digitalWrite(valvePin, LOW);//propane off
    analogWrite(fanPin, 170);// Set fan to mid speed; range is 0-255
    analogWrite(igPin, 0);// igniters off until called
  
  sensors.begin(); 
  //delay(2000);
  get_temps();

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


  Serial.println("Mosquito Magnet Mega Defender V" + rev);
  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.");
  oled.clear(); oled.set2X(); oled.println("SD CARD OK"); oled.print(" REV " + rev);oled.set1X();
    myFile = SD.open("Magnet.txt", FILE_WRITE);   // if the file opened, write to it:
  if (myFile) {
    myFile.println("Mosquito Magnet Mega Defender V" + rev);
    myFile.println("loop#,hours,dayofmonth,month,year,hour,min,sec,hours,time,date,stat,stat2,temp,amb_Temp,delta_Temp,humidiy,a2Temp,total_hrs,propane_hrs,total_days, propane_days, gas_sensor,thermistor");
    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,gas_sensor,thermistor");
    myFile.close();
  }
  get_temps();
  readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  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();
  iMinute = minute;
  
  refresh_oled(); //Show initialize screen to check temp sensors
 
  delay(1500);// wait  to allow OLED screen to be read and settle gas sensor
  
//###  Detect short power interupt, hot section still warm
   if (dTemp > 100 || dTemp < -5) { // check for a temp sensor failure
     stat = "TEMP FAIL";
     shut_down;
   }
  int cool_minute;
  cool_minute = iMinute;
while (dTemp>8 && cool_time < 16){// run fan, cool down until hot temp is within 8 degs or 16 minutes has passed
  stat = "POWER LOSS";
  analogWrite(fanPin, 255);// Set fan to max speed; range is 0-255
  readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  refresh_oled;
      if (cool_minute != minute){cool_time ++; cool_minute = minute;}
  file_write(); serial_write(); refresh_oled();bluetooth();
}
  file_write(); serial_write(); refresh_oled();bluetooth();
}

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);
   
//#####################  || is "normal" between breaks ; using "&&" runs 24/7 for testing and troubleshooting
  if ((hours > 0.25 && hours < 6.25) || (hours > 9.75 && hours < 16.00)){ // sleep routine; sleeps late at night and mid day
           stat = "SLEEPING";
           start = false;
           digitalWrite(valvePin, LOW);//propane off
           analogWrite(fanPin, 230);// Set fan to mid-high speed
   }
           
   else {  // trapping routine
       
       if (!start){ignite_cycle();} // runs igition if this is the first loop pass the start time 
       stat = "TRAPPING";

       if (dTemp < lightoff -1){stat = "SHUTDOWN ";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 = "WARM UP ";
    Serial.println("inside ignite_cycle"); 
    analogWrite(fanPin, 160);// Set fan to mid-low speed for ignition; range is 0-255
    refresh_oled();
    
    for (int zz = 0; zz<= 255; zz++) { // start igniter slowly, about 19 seconds to max power
        analogWrite(igPin,zz); Serial.print(zz);
        if (zz > 210){ digitalWrite(valvePin, HIGH); Serial.print("   propane on");}//propane on at about 15 seconds
        delay(75);Serial.println();
      }
    stat = "POST IGN"; 
    initTime = millis()/1000;
    get_temps();
    iTemp = temp;
    stat2 = "igniter on";
    refresh_oled();
    Serial.println("  POST IGNITER ");delay(1500);
    
    while (elapsed <= start_time && dTemp < lightoff) {
        x++; stat= "IGNITION";    
        iMinute = minute;
        readsec = millis()/1000;
        elapsed = (readsec - initTime); // provides run time
        get_temps();
        readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
        Serial.print("  x= "); Serial.println(x);
        if ((temp-iTemp) > 1.65 && elapsed > 55) {
          analogWrite(igPin, 0);  //  turn off igniter, stay in ignition monitoring loop til start_time or lightoff temp is reached         
          analogWrite(fanPin, 225);// Set fan to mid-high speed
          stat2 = "igniter off";
        }
        
        Serial.print("IGNITION   delta Temp "); Serial.println(temp-iTemp); Serial.print("temp "); Serial.println(temp); 
        Serial.print("aTemp "); Serial.println(aTemp); Serial.print("Elapsed "); Serial.println(elapsed); 
        Serial.print("  gas sensor "); Serial.println(gas_sensor);
        Serial.print("  thermistor "); Serial.println(thermistor);
    
        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(temp-iTemp);
        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.print(hours);myFile.print(","); myFile.print(gas_sensor);myFile.print(","); myFile.println(thermistor);
        myFile.close(); 

        file_write();
        
          oled.clear(); oled.set2X();
          oled.println(stat); oled.set1X();oled.println();
          oled.print(temp); oled.print("    ");oled.println(temp-iTemp);
          oled.print("temp"); oled.println("   Temp rise"); oled.println();
          oled.print(" Ignition time: "); oled.println(elapsed); 
          oled.print(stat2);oled.println("   ");
          
          bluetooth();
    }

    analogWrite(igPin,0); // stop igniter if still on

    if (elapsed > start_time || dTemp < lightoff){
          start = false;
          stat = "SHUTDOWN ";
          stat2 = "No Ignition"; Serial.println(stat2);oled.println(stat2);
          shut_down(); }
          
    else {start = true; x = 0; // good lightoff
          stat2 = "Good Ignition"; 
          analogWrite(fanPin, 240);// Set fan to mid-high speed
          Serial.println("Ignition cyle complete.  Good lightofff");oled.println(stat2); delay(1000);}
}

 // 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);
  *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(){
      digitalWrite(valvePin, LOW);//propane off
      analogWrite(igPin, 0);//be sure ignition is off
      analogWrite(fanPin, 215);// Set fan
      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 temp
  aTemp = sensors.getTempFByIndex(0);// Ambient location 
  cTemp = sensors.getTempFByIndex(2);// 3rd location temp
  dTemp = temp - aTemp;
  chk = DHT.read11(amb_temp);
  a2Temp = DHT.temperature*1.8+32;
  gas_sensor = analogRead(gasPin);
  thermistor = analogRead(thermistorPin);
  delay(1600);
  
}  

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 ignited
            
            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(hour); myFile.print(":"); if (minute < 10){myFile.print("0");} myFile.print(minute); myFile.print(",");
                 myFile.print(month); myFile.print("/"); myFile.print(dayOfMonth); myFile.print("/");myFile.print(year); 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(a2Temp);
            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.print(",");myFile.print(gas_sensor);myFile.print(","); myFile.println(thermistor);myFile.close(); 
       }
}

void refresh_oled(){ //Push data to the OLED display
     oled.clear(); oled.set2X();
     if (disp){
         oled.println(stat);//oled.set1X();
        oled.print(temp,1); oled.print(" ");oled.println(aTemp,1);//oled.print("  ");oled.println(DHT.humidity);
        //oled.println(" temp   ambt   humid.");
        oled.print("Days: ");oled.println(total_days,2);
        disp = false;
     }
      else {  
        oled.println(stat);
        oled.print("P_days:");oled.println(propane_days,2);
        oled.print("Time:");oled.print(hour, DEC); oled.print(":"); oled.println(minute, DEC); 
        disp = true;
      }
}
        
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("Time: ");Serial.print(hours); Serial.print("  run hrs ");Serial.println(total_hours,3);Serial.print("  Thermistor: "); Serial.println(thermistor);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(",");
        BTserial.print(gas_sensor,3);BTserial.print(";"); // last output needs to have the ";"
}
Re: Defender Arduino Design
June 01, 2021 02:21PM
beads Wrote:
-------------------------------------------------------
>
> Of note, I hove not used a single CO2 cartridge since 2019. I never understood the purpose of the
> cartridges, and they didn't seem to really help prior to switching to the Arduino controller. If any
> one has a solid understanding of exactly what the CO2 flushing process achieves, it would be interesting
> to know. There have been hundreds of lightoffs without any CO2 used, and a dozen or so propane
> tanks amongst the four Mega Defenders that have been modified.

I have always speculated that the CO2 cartridges are just to blow out the nozzles, as they tend to get clogged up with contaminated particles from the propane. I have not found them very useful or effective and instead clean out my nozzles with a non-residue cleaner, like MAF cleaner. I always clean the nozzles of any new MM I procure used, but have to say that in the last 5 years or so, I haven't had to clean the nozzles of any of the MMs that I have been running. Perhaps my propane supply is clean and is not contaminating the nozzle...
Re: CO2 cartridges
June 03, 2021 11:07PM
I have used a tire pump to blow air through the nozzle. Perhaps not a great idea as that air contains humidity and pump residue, but that has worked in a pinch to get the trap started. The CO2 would be pure and dry, but the small cartridge is not very effective. Also, if the valve is open, it can back feed the regulator, and damage that as well.

Ultimately, I have to disassemble and clean the nozzle with brake cleaner (mostly acetone with a bit of toluene). Testing the nozzle with the tire pump yields a pressure of about 35-45 psi for a new or cleaned nozzle, much higher (~100 psi) for clogged nozzles. Unfortunately, the newer electric tire pumps are all automatic now, and won't work for such a use. I am not looking forward to this on my newish Patriot, but it is getting unreliable. At least the nozzle can be removed without opening the combustion chamber.



Edited 1 time(s). Last edit at 06/03/2021 11:10PM by dev.
Re: CO2 cartridges
June 04, 2021 02:34PM
Coincidently, just as I mentioned that I haven't had to clean out my nozzles in a while, my main Independence had trouble starting this season. It would take too long to get up to temperature. A quick cleaning of the nozzle took care of that.

My cleaning method consists of removing the nozzle from the valve assembly, separating the bronze filter from the nozzle tip, and soaking both of them in cleaner. After that, I blow out both items with an air compressor. You can see if the nozzle tip is ok based on the cleaner spray pattern that you get when you initially blow it out. If you get a nice cone pattern, then you're probably good. If you get a distorted pattern, then it probably needs more cleaning. The nozzle tip can be disassembled to clean out further, if the solvent alone doesn't do the job.
Re: CO2 cartridges
June 05, 2021 12:27PM
I started a long entry here, but have moved it to the blog.

I should mention a few more details about cleaning here. I use brake cleaner, and haven't tried MAF (perhaps more effective). After removing the filter, place both into a 4 oz glass jar, cover with solvent, and place the covered jar into a small ultrasonic cleaner filled with warm water, and run for about 30-45 minutes. This seems to work.

I then test the nozzle(s). I was fortunate enough to acquire a used Mosquito Magnet valve from ebay. I block the propane line intake port, screw the nozzle into the valve, and connect a prior generation electric automobile tire pump with gauge to the Schrader valve input. With the pump on, the cleaned nozzle reads 35-45 psi vs the >60 psi from an obstructed nozzle. If the nozzle reads high, it gets another round of cleaning. This test also works on a trap.



Edited 1 time(s). Last edit at 06/05/2021 02:48PM by dev.
Re: CO2 cartridges
June 05, 2021 10:17PM
I rather suspect that when we have problems, it happens on the inside of the nozzle tip.


The cutaway of the nozzle (and my disassembly) indicates that the choke points for the nozzle are likely to be at the distributor and it's tangential slots, as well as between it and the orefice. You can dismantle it to clean it, but soaking with cleaner and then blowing out with compressed air multiple times seems the easiest way to expel the blockages. That's probably the intent of the CO2 cartridges, but without any solvent, it's probably of limited use. But at least you didn't have to remove the nozzle to clean and blow it out with solvent.
Sorry, only registered users may post in this forum.

Click here to login