Jump to content

Stargazers Lounge Uses Cookies

Like most websites, SGL uses cookies in order to deliver a secure, personalised service, to provide social media functions and to analyse our traffic. Continued use of SGL indicates your acceptance of our cookie policy.

sgl_imaging_challenge_banner_dslr_mirrorlesss_winners.thumb.jpg.9deb4a8db27e7485a7bb99d98667c94e.jpg

brown_rb

Arduino Dew Controller Feature Rich

Recommended Posts

Hi

I have finished my dew controller, based on Arduino Nano board, and am posting details here.

The pdf document lists all the features, pictures of the design build, the code, schematic, parts list, testing, assembly and other things.

I have posted a youtube video of the controller working at 

It uses both serial and a LCD1602 though support is already there for a LCD2004.

It supports DHT11/21/22/33 sensors as well as DS18B20 temperature probes.

It is a two channel independent pwm controlled dew controller and requires 12VDC.

It has override switches to boost pwm pwr to the dew straps to 100%

It has three temperature tracking algorithms as well as adjustable offsets for calibrating ambient temperature value as well as moving the entire temperature monitoring bands up or down.

It has LED status for PWM power and cooling fan speed.

It can be used with a windows app to provide realtime monitoring/logging/updating, or in standalone mode, or via rs232 interface.

All for less than $45 in parts.

I will post more later, for now, enjoy,

Robert

OVERVIEW

This is a DIY Dew Controller based on an Arduino Nano, bread boarded and enclosed in a project hobby box.

SPECIFICATIONS

·         Supports standard dew straps such as DEW NOT via PWM output, 12VDC

·         Supports two independent controlled dew channels

·         Supports two independent temperature probes DS18B20

·         LCD1602 (or LCD2004) display of all settings

·         Optional remote control and logging via USB

·         12VDC@5A PSU required

·         Reverse voltage protection on 12VDC input

·         Each dew channel powered by TIP120 medium power Darlington (inbuilt reverse protection)

·         TIP120 transistors support up to 2.5A to each strap (recommend using TO-220 heat-sink)

·         Dew channels (2 supported) are PWM adjusted depending upon dew point/algorithm

·         Controller automatically adjusts power to dew straps (0, 25%, 50%, 75%, 100%) as required

·         Supports manual override switches to boost PWM power to 100% for each dew channel

·         Supports remote control via serial port or Windows Application

·         Temperature/Humidity Sensor uses DHT11 (or DHT21/22 for higher accuracy)

·         LEDS indicate if PWR is on to dew channel (brightness indicates % pwr applied)

·         12VDC cooling fan support, speed PWM controlled with RGB LED indicator

·         Key session state values saved in EEPROM for later retrieval

·         Three tracking algorithms, DewPoint, Ambient and MidPoint with adjustable band offsets

PURCHASE LIST

Details

Supplier

USD

DHT11 Temperature and Relative Humidity Sensor (1.99)

survy2014

1.99

Heat Sink with screw  (17x15x7) 3pcs

happy-electronic

3.80

Transistors TIP120 TO-220 NPN Medium Power Darlington 3pcs

jk_parts

2.49

LCD 1602 I2C Module

hkseller2014

2.98

LCD 1602 Module

seemmy

1.95

PCB Circuit Board Prototyping Stripboard 94x53mm (19x34 holes)

tayda2009

1.29

Thermometer probe DS18B20 2pcs

alice1101983

3.68

Arduino Nano V3 CH340G

alice1101983

4.67

RCA Panel Mount Female 2pcs

mid0808

1.61

LED Blue 3mm Bezel 12V + resistor panel mount 2pcs

bestshop2008hk

1.80

Stereo Female Jack 3.5mm 2pcs Chassis Mount

Mouser Electronics

1.86

Stereo Plug Male 3.5mm 2pcs

louisliu2009

1.98

Diode 10A10 10A 1000V

satisfyelectronics

1.48

Power Socket Panel Mount 2.5mm x 5mm

dailyappliance2010

0.99

Power Plug Male 2.5mm x 5.5mm x 14mm

dailyappliance2010

0.99

Toggle switch mini ON-OFF 3pin SPDT 2pcs

ymvon

1.61

Panel Mount fuse holder 5x20mm

eddiestore2008

1.21

Fuses, Glass, Fast Blow, 5x20mm, 6A

louisliu2009

0.99

Fan 40mm 12VDC Ball Bearing 0.2A

so.great.value

2.42

RGB LED module with limiting resistors (Keyes-016)

chip_partner

1.94

Header pin 2.54mm Female Strip

louisliu2009

0.99

Plastic Hobby Enclosure (130x68x44mm), screws, mounting blocks #MBF-22

All Electronics

3.50

Resistors 4.7K 2pcs, 1.2K 6pcs, 1M 4pcs

Wire, 12VDC 6A Supply

DHT21 Sensor  (alternative with better accuracy - $3.98)

alice1101983

Plastic Hobby Enclosure (164x100x51mm), screws, mounting blocks(13.00)

AliExpress.com

LCD2004 I2C module (9.00)

eddiestore2008

Bidirectional level shifter 3.3v to 5v (Not yet implemented $8.62)

Sparkfun

Bluetooth RF module HC05 6pin (Not yet implemented $5.43)

alice1101983

 

Total

44.23

The controller prototype uses the “Mini USB Nano V3.0 ATmega328 16M 5V Micro-controller CH340G board for Arduino AL” from Ebay supplier alice1101983. This board does NOT use an FTDI chip so there will be no issue powering the board from 12VDC via VIN. The board also has drivers for Windows, Mac and Linux.

 

 

POWERING THE NANO

The Nano can derive power from the mini-USB cable, as well as an external source connected to Pin 30, VIN. This pin accepts between 7-12VDC (maximum 20VDC), so the 12VDC rail can be connected to VIN (Pin 30) to supply power to the Nano board, as 12VDC is required to power the dew straps.

The EEPROM data is overwritten when a new sketch is downloaded (for example a software update). To overcome this, the key session state variables are reinitialized with default values if the EEPROM data has been found to have erased.

The Arduino Nano can derive power from the mini-USB, VIN (pin 30) or 5V (pin 27). The Nano will select the highest voltage source (which will be VIN when the 12VDC is connected). The FTDI FT232RL chip on the Nano is only powered if the board is being powered over USB. As a result, when running on external (non-USB) power, the 3.3V output (which is supplied by the FTDI chip) is not available and the RX and TX LEDs will flicker if digital pins 0 or 1 are high.

This means we cannot connect VIN to 12VDC as we would lose the FTDI RS232 connection. If so, we could use an RS232 connector wired direct to digital pins 0 (RX) and 1 (TX) rather than use the mini USB cable. It would mean having to place a connector on the side of the enclosure, wire it to pins 0 and 1 of the Nano, and install a RS232 cable back to a COM PORT or RS232-USB adapter.

HOWEVER – using the CHSER board as recommended for this project, that does not use the FTDI chip, this limitation is removed. It is strongly recommended to use this board.

The Nano typically will be powered from 12VDC and be connected to the computer via a mini-usb cable (though not required).

To power ON the controller – Connect the mini-usb cable (if required), then turn ON the 12VDC

To power OFF the controller – Turn OFF the 12VDC then disconnect the mini-usb cable

MODES OF OPERATION

The controller can operate in a number of different modes, depending on the user requirements

·         Local Automatic
The controller operates on 12VDC and the mini-usb cable omitted. The controller will function as a standalone device, but the user can still use the toggle switches to override the power to the dew straps

·         Local/Remote Computer
The controller operates on 12DVC and the mini-usb cable connects the controller to a computer. The computer can send serial commands to the controller to alter parameters such as tracking mode. The user can still use the toggle switches to override the power to the dew straps

·         Remote Windows
The controller operates on 12VDC and the mini-usb cable connects the controller to the computer. The controller is running the x.xx_win version of the Arduino code. The Windows application sends commands to the controller and values are displayed in a GUI

  • Like 3

Share this post


Link to post
Share on other sites

UPLOADING THE DEW CONTROLLER CODE TO THE NANO

Please use the latest Arduino Sketch IDE software (1.5.7 or higher) with this project.

Select Nano from the Tools > Board menu. Select the correct serial port from the Tools > Serial Port menu. Press the upload button in the Arduino environment. The board will automatically reset and the sketch will be uploaded.

REVERSE VOLTAGE PROTECTION ON 12V AND FUSED PROTECTION

A 10A10 diode rated at 10A provides reverse voltage protection on the 12V supply rail. The current draw at 100% power to both Dew-NOT straps would be in the region of 1-4A depending on dew strap size, so this is adequate protection. The forward voltage drop across the 10A10 diode is around 1.1V. A 6A quick blow fuse provides excess current draw protection.

LCD1602 DISPLAY

The controller uses a 16 character by 2 line I2C module to display the various parameters. Values which are displayed include

                Ambient air temperature

                Relative Humidity

                Dew Point

                Tracking Mode

                ATBiasOffset

                FanSpeed

                Ch1 and Ch2 temperature

                Ch1 and Ch2 pwm power levels

Support is included for a larger 2004 (20 character by 4 line) I2C module, which is Pin compatible and requires no hardware changes. The controller software already supports both the LCD1602 and LCD2004 types. To use a LCD2004, the define MYLCDTYPE must be changed to LCD2004 and the code recompiled and downloaded to the controller.

The use of the larger LCD2004 permits displaying temperature values to 1 decimal point. If the LCD1602 is used, temperature values are rounded to the nearest integer value for display and all values are displayed at one time. For the LCD1602, the values are displayed using a two second delay between alternate screens. 

  • Like 1

Share this post


Link to post
Share on other sites

DHT11 SENSOR (AMBIENT TEMPERATURE AND RELATIVE HUMIDITY)

The prototype was tested with a DHT11 sensor. The use of the cheaper DHT11 sensor is more than adequate for this application.

It is important to mount the DHT11 sensor on the outside of the hobby box enclosure. The sensor needs direct contact with the surrounding air in order to measure the temperature and humidity correctly. Mounting inside the hobby box enclosure would mean it would give erroneous readings caused by lack of air circulation and heat generated from the surrounding electronics inside the enclosure. The sensor is attached to the outside of the enclosure and wires routed through the enclosure to the main board.

The LCD displays the Ambient Temperature and Dew Point in Celsius, and the Relative Humidity as a percentage.

The DHT11 sensor has an accuracy of +- 2 degrees Celsius for ambient temperature and +-5% for relative humidity. The ambient temperature can be compensated using an offset value in the controller (ATBias Offset). The sampling rate interval (time between subsequent readings) is limited to once per second.

Calibration of the ambient temperature reading from the DHT11 sensor has been added via an offset (called ATBias). This gives the user the ability to add or subtract constant values to the ambient temperature reading to account for minor variation. My sensor always returns an ambient value which is around two degrees Celsius more than it should, so using the offset is an easy method to adjust the ambient temperature value at the time it is read from the DHT11. I have found that my unit is about +2 degrees Celsius in error, so new commands have been added which allow the setting of the Ambient Temperature offset values to -6, -4, 2, 0, 2, 4 and 6.

For greater accuracy, the DHT33, DHT22 or DHT21 sensor can be used and is supported with no change to hardware (pin compatible) and minimal controller software code (redefine of MYSENSOR variable and recompile code). The DHT21 sensor has an accuracy of +- 0.5 degrees Celsius for ambient temperature and +-3% for relative humidity. The sampling rate interval (time between subsequent readings) is limited to once every 2 seconds. The DHT21 sensor is slightly more expensive than the DHT11 sensor.

It is important to realize that the application does not require super accurate measurements and that a tolerance of a couple of degrees is more than adequate. By the use of temperature band offset values for the tracking mode algorithm and the use of a bias offset value for ambient temperature, finer adjustments can be made and in practice, users should not notice any lack in performance when using one sensor compared to another. 

Share this post


Link to post
Share on other sites

TEMPERATURE PROBES

Two independently controlled channels are provided. The temperature probes are DS18B20 and the resolution is set by the controller to 9-bit giving 0.5 degree of resolution. The accuracy of the measured temperature is within 0.5 degrees Celsius.

The wire ends of the probes are soldered to a 3pin Audio Stereo Male connector. Two 3pin Audio Stereo female jacks are mounted on one side of the hobby box and connected to the main board. Disconnection or reconnection of the probes must be done when power is OFF. VCC and GND are wired separately. This permits a slightly faster read of temperature than if the probes operated in parasitic mode.

The sensor end of the probe is fitted so that it just slightly fits under the heat strap or sticky tape is used to secure the sensor as close as possible to the dew strap. The entire sensor should not be placed under the dew strap, as the sensor would end up reading the temperature of the dew strap rather than the temperature of the telescope optics. In addition, do not locate the sensor a long way away from the dew strap, as then you might overheat the telescope optics. Locate the sensor near (say 1/4" away) the dew strap.

The LCD unit displays the temperature for each probe in Celsius or Fahrenheit as an integer but all internal calculations are performed using float variables.

The temperature probes and dew straps are combinations and form a feedback loop. This means probe1 pairs with dewstrap1 and probe2 pairs with dewstrap2.  There is one temperature probe per dew strap, so once you have identified probe1, you should label it so that you know it goes with dew strap 1 and plug it into the correct socket on the controller. Each temperature probe uses a separate pin, with probe 1 using pin 7 and probe 2 using pin 8. 

Share this post


Link to post
Share on other sites

DEW-NOT STRAPS

The unit provides two independent channel outputs which are pulse width modulated at 12VDC to power two dew straps (typically one per OTA, or you might use two for one large OTA). The unit was tested with two Dew-Not straps. Connection is via standard RCA female connectors mounted on the side of the hobby box. Two LEDS provide an indication of pwm power to each dew strap; the brighter the LED, the more power is being output. In addition, the LCD displays the power for each channel. Available power settings are 0, 10, 20, 50, 75 and 100% for each channel.

The dew straps should be placed as close as possible to the lens assembly or corrector plate of the telescope for maximum efficiency. Avoid running at 100% power for extended periods of time. Disconnection or reconnection of the dew straps must be done when power is OFF.

Heat sinks should be fitted to both TIP120 transistors. Space is limited on this board so it is best to use the smaller heat-sink size (17x15x7). 

Share this post


Link to post
Share on other sites

12VDC POWER SUPPLY FOR DEW STRAPS

A separate 12VDC supply rated at 5A or higher is required for power to the dew straps. A 10A10 diode provides reverse voltage protection. The ground of the 12V power supply must be connected to the ground pin of the Arduino Nano. At least 1V is dropped by the 10A10 diode.

You need to be aware that using a higher voltage source (like a 13.6VDC car battery) will increase the current in the dew straps, generating more heat. Heat within the enclosure will also increase due to the increased current that the TIP120 transistors are switching. This places an extra load on the circuit wires and fuse capacity. This heat must be dissipated through the provision of air vents and a cooling fan.

The current system is designed to work at a nominal 12VDC supply for the dew straps.

COOLING FAN

A 12VDC cooling fan (40mmx40mmx10mm) is PWM controlled to provide air flow through the enclosure to reduce build-up of heat caused by the TIP120 transistors switching on and off the dew straps.

Air vents on one side provide an inlet for air flow, whilst the fan mounted on the opposite side will draw air through the air vents and out through the fan. The cooling fan uses pin5 and is PWM controlled at speeds of 0% (OFF), 50%, 75% and 100%. Serial commands o (fan on, use 100%), 5 (50%), 7 (75%) and s (stop fan) are used to control the cooling fan.

The prototype used a ball bearing fan for less vibration. The PWM setting can be used to reduce vibration if the vibration is an issue at higher PWM values. The 5V is level shifted to 12V via an additional TIP120 transistor. The cooling fan has a current draw of around 200ma at 100% PWM which can be easily handled by the existing 12V power rail.

An RGB LED indicates the fan PWM setting.

                0%          All LEDS OFF

                50%        Green LED ON

                75%        Blue LED ON

                100%     Red LED ON

To further reduce possible vibration caused by the fan, it is possible to mount some rubber strips between the enclosure and the fan which greatly assists in reducing vibration at high PWM settings. The amount of vibration caused by these small fans is minimal and should not cause any mount issues. The prototype used thick double sided plumbers tape to secure the fan to the enclosure, providing isolation of motor vibration as well as not requiring any fan mounting screws (which would only serve to transmit the fan vibration to the enclosure).

The use of the cooling fan is mandatory for safe and reliable operation of the controller.

NOTES: DO NOT PLUG/UNPLUG ANY EXTERNAL DEVICE WHEN ARDUINO OR 12V IS ON

Always connect/disconnect temperature probes and dew straps with POWER OFF

TOGGLE OVERRIDE 100% CHANNEL POWER SWITCHES

Two toggle switches (SPST ON-OFF) connected via a voltage divider network provide an option of overriding the power setting to each dew channel to maximum (100%) when activated. If dew is forming, a sudden boost to heat the telescope optics is available by using the override feature. Just remember to turn it off as it does not turn off by itself.

The toggle switches are implemented using a voltage divider network and a single analogue pin (A0). The override switches could be omitted if the intention is to use the dew controller via computer, as the remote control software provides this feature (as well as the ability to disable the override feature after a time elapsed period at 100% maximum of 2 minutes).

PROJECT ENCLOSURE

A plastic project hobby enclosure was used to hold the controller board and various components and sockets. The prototype enclosure had the following dimensions.

PROJECT BOX W/ MTG FLANGE, 130 x 68 x 44mm

As space is very limited with this enclosure, it is recommended to use a larger enclosure. The production version had the following dimensions

PROJECT BOX, 164 x 100 x 51mm

Share this post


Link to post
Share on other sites

A NOTE ABOUT TEMPERATURE VALUES

The display of temperature values can be either Celsius (default) or Fahrenheit. Values are calculated in float type by the software, but are displayed as rounded integer values on the LCD1602. The serial monitor displays the values to one decimal place.

TEMPERATURE PROBES

The controller automatically detects the number of DS18B20 probes connected on startup or reset. Consider the case where only one probe is connected. The number of probes will be 1. The temperature value of the absent channel is displayed on the LCD as – and its pwm setting set to 0. For serial port messages, the temperature of that channel (without a probe) is set to -1.

If the channel does not have a probe it is considered disabled, and thus trying to apply a 100% power override command is ignored.

The temperature sensor probes can be plugged into any sensor socket. The order is not important. The controller implements each probe on a different Arduino pin, which allows easy identification of a temperature probe, connected to a socket.

A NOTE ABOUT DECIDING HOW MUCH POWER TO APPLY TO THE DEW STRAPS

There needs to be a way to calculate how much power to apply to the dew straps based on some value (tracking mode) as well as a range of temperature bands (range) over which the dew strap power is altered.

In general, most dew controllers operate relative to the dew point temperature, and try to maintain the telescope optics temperature at some delta point above the dew point.  A fast dew point calculation is implemented within the program, and is reliable where the relative humidity is 50% or higher.  If operating in a low relative humidity environment, an alternative dew point calculation routine is called to provide a more accurate result (but is fractionally slower).

The controller software provides an offset bias that can be added or subtracted to the power calculation routine, so that the temperature range/band over which calculations are done can be moved up or down (over +-4 degrees). The commands < and > allow the user to decrease or increase the offset as desired. A range limit has been imposed on the amount of offset that can be applied, and is controlled by the global defines OFFSETPOSLIMIT and OFFSETNEGLIMIT (currently set to +4 and -4 respectively).

The offset bias provides a fine adjustment of the algorithm that is used to determine the power output to the dew straps. In general, pressing < raises the temperature value at which the power will be applied, whilst pressing > lowers the temperature value at which the power will be applied. So if you think that the OTA temperature is a little on the low side, you can press > to raise the trigger level at which the OTA temperature is triggered.

The controller software provides THREE different methods for adjusting dew strap power, called tracking modes; dew point tracking or ambient tracking or Midpoint tracking. Dew point tracking tries to maintain the OTA temperature about 4-6 degrees above dew point, whilst ambient tracking tries to maintain the OTA temperature at or near ambient (which should always be higher than the dew point). Midpoint tracking tries to keep the OTA temperature midway between the dew point and ambient temperature. The serial commands a, d and m provide for selection of ambient, dew point or midpoint tracking modes.

Users are advised to spend an evening session monitoring the values, trying various tracking modes and offset values to determine what the feel is best for their equipment setup. Having the flexibility of adjustment provided by this dew controller should meet even the most demanding of situations.

MANUAL OVERRIDE OF POWER TO DEW STRAPS

The controller implements overriding the power to the dew straps and applying 100% to either channel. There are a number of ways to do this.

The toggle switches (one per channel), when ON, overrides the power calculation and applies 100% power to the associated channel (this is referred to as Override Mode). When the toggle switch is OFF, power for that channel is set to 0%, and then on the next power calculation the correct power will be determined for that channel (this is referred to as Normal Mode).

The other way to override power is to use the serial commands 1, 2 and n. The command 1 sets the power level for channel 1 to 100%. The command 2 sets the power level for channel2 to 100%. To revert to normal mode (turn off the override), the command n must be sent. Pressing n (followed by enter key) turns OFF the power level override to both channel 1 and channel2.

A NOTE ABOUT CURRENT DRAW RELATED TO DEW-NOT STRAPS

The following table, provided from Dew-Not, lists the currently available Dew-Not straps and their ratings. Note that powering two dew straps DN005 would equate to about 1.2A of current. The system can easily handle two DN015 dew straps at the same time running at 100%.

Share this post


Link to post
Share on other sites

A NOTE ABOUT THE SERIAL COMMAND INTERFACE

Set the serial port monitor to “newline”

To send a command, type the letter then press Enter on your keyboard. Commands are case sensitive. Typing h followed by enter displays the list of available commands. The menu of commands looks like

------------------------

                Tracking = Dew Point, Normal Mode, Offset=0, ATBias=-2

Menu

                h  display commands

                1  override, 100% pwr to ch 1

                2  override, 100% pwr to ch 2

                n  normal mode

                a  Track ambient

                d  Track dew point

                m  Track midpoint

                c   Celsius (default)

                f   Fahrenheit

<  Dec offset

                >  Inc offset

                z  Zero offset

                0  Fan ON, 100%

5  Fan 50%

7  Fan 75%

s  Fan OFF

e  ATBias -4

r  ATBias -3

t  ATBias -2

y  ATBias -1

u ATBias 0

I  ATBias +1

o ATBias +2

p ATBias +3

w  Save variables to EEPROM

Typing a followed by enter would set the tracking algorithm to track ambient temperature

Values are written to the LCD as well as the serial port. Commands are case sensitive.

LCD DISPLAY OUTPUT

                Startup Messages

                Dew Control

                © RBB v2.xloc

                Probes=2

                Normal Operation LCD1602                                         LCD2004

                AT:12  HU:65                      // line 0                                                AT:12.2    HU:65 // line 0

                DP:7    TM:D Fx                  // line 1                                                DP:7.4      TM:D Fx            // line 1

                C1:10  C2:8 xx                     // line 0                                                C1:10.7    C2:8.1   xx         // line 2

                P1:20  P2:100                      // line 1                                                P1:20        P2:100                // line 3

SERIAL MONITOR OUTPUT

                Startup Messages

                                Dew Controller: © RBB v2.xloc

                                Number of Temperature probes found: 2

               

                Normal Operation

                                Normal Mode, Track: DEWPOINT, Offset: x, ATBias xx

                                AT:xx, HU:xx%, DP:xx.x, TM:D, Fx

                                C1:xx, C2:xx, P1:xxx%, P2:xxx%

post-33939-0-21068800-1410983231.jpg

Share this post


Link to post
Share on other sites

TEMPERATURE TRACKING ALGORITHMS

Probe Temp

Dew Temp (DP)

Ambient Temp (AT)

MidPoint (AT - (AT-DP)/2)

+9

0%

AT

0%

+8

0%

=AT < 3

10%

+7

0%

= AT - (AT-DP) / 2

20%

+6

0%

= AT – ((AT-DP)/2)+2)

50%

+5

10%

<=DP

100%

+4

20%

+3

50%

+2

75%

+1

100%

=

100%

0%

-1

100%

10%

-2

100%

10%

-3

20%

-4

20%

-5

50%

-6

50%

-7

75%

-8

75%

-9

100%

-10

100%

Share this post


Link to post
Share on other sites

EEPROM DATA

The Nano provides EEPROM storage space (512 bytes-ATmega168, 1 KB-ATmega328) which can be used by program code to remember the state or value of key user settings/variables.

Important user adjustable settings are stored in EEPROM so that their state is remembered between sessions. The variables stored in EEPROM are

TrackingState;                   // keeps current temperature tracking algorithm

offsetval;                             // keeps the offset value applied to the temperature tracking algorithm

                fanspeed;                           // indicates the fan speed

                ATBias;                                 // used to add/subtract an offset value from the Ambient Temperature

                                                                // reading from the DHT11 sensor

The program, on startup, tests to see if the EEPROM data exists. If the data is corrupted or does not exist, the data is re-created and written back to EEPROM.

During program operation, if commands are received by the controller to adjust some of these values, they are stored BUT NOT written back to EEPROM at the time of change. The user needs to explicitly send a w command to save the variables back to EEPROM before turning off the controller.

It is unlikely that users will every reach the limits of 10,000 writes for EEPROM data in normal operation.

The include files <EEPROM.h> and “eepromanything.h” is required.

PROGMEM DATA

Constant strings have been moved to PROGMEM. This reduces the data requirements at the cost of a small increase in code size and slightly slower execution (which is not an issue).

The include file <avr/pgmspace.h> is required.

ARDUINO CODE BASE X.XX_WINX – SERIAL /LCD + WINDOWS APPLICATION ONLY (V1.98 OR HIGHER)

This release version has major changes to the serial port command interface. This allows a Windows based program to monitor, display and graph the dew controller parameters. The windows code is written in Lazarus Pascal and has been tested on Windows 7/64bit. Updates can be automated at a rate of 10s, 20s, 30s, 1m and 2m intervals or manually. This version only works with a special x.xx_winx only version of the Arduino code. Values are displayed on the LCD and in a Windows GUI.

Additional support is provided to turn OFF the 100% override to either channel after a 2 minute delay to prevent accidental overheating of the OTA (as a precautionary measure in case the user forgets to turn this override feature off). There is no shutdown feature in the x.xx_local Arduino code however.

The Windows application also uses an INI file (Dew_Controller.ini) in the program file directory to keep track of some of the important interface settings. When the program is run, those settings are loaded from the INI file and update the Windows application display. Other system settings are stored by the controller in EEPROM.

The settings/parameters kept in the INI file are

[iNIDB]

; Save as Dew_Controller.ini

OTA1=SV102

OTA2=ED80T-CF

Cycle=10000

OTA1 is the text description for Channel1, OTA2 is the text description for Channel2, Cycle is the refresh rate in milliseconds when in automate mode.

Whenever these settings are altered on the form, the new value is saved back to the INI file, so that the INI file tracks the current settings on the form.

To set the OTA1 string, type the desired text into the “General Text Entry’ box; left click on the Channel1 temperature label and left click on the Channel1 power label. The labels are updated with the new values and saved to the INI file.

The x.xx_winx version does not support the controller toggle switches to override the power settings as this is controlled remotely via the application. If the switches are present, they are ignored.

This means the user could use the controller remotely using the Remote version of the Arduino code, or manually using the Local version of the Arduino code.

post-33939-0-07020500-1410983574.jpg

  • Like 1

Share this post


Link to post
Share on other sites

POSSIBLE FUTURE BLUETOOTH SUPPORT

In a future release, Bluetooth support could be added to the Dew controller, using a HC-05 module and bi-directional level shifter to convert between 3.3V and 5V TXD/RXD signals for the Bluetooth module. Both Arduino Serial TXD/RXD and Bluetooth Serial support will be available.

A user can then use Bluetooth to implement a wireless connect to the dew controller, and run either the Windows application (which will be enhanced to support Bluetooth) to control and monitor the dew controller, or via an Android phone (initially using a simple terminal Bluetooth app) with a dedicated Android app (planned for a future release).

A NOTE ABOUT POSSIBLE EXPANSIONS AND CONFIGURATIONS AND COST REDUCTIONS

There is still sufficient space for program expansion as well as data storage. The current free pins are D2, D11, D12, A1, A2 and A3 (D2/A1/A2/A3 planned for Bluetooth).

The dew controller could be implemented as a single or dual channel controller. As there are no spare PWM pins left, adding additional channels are not feasible for the Nano (unless the fan-speed RGB LED is omitted and associated code removed).

However, this could be done using a Mega2560 board (as Pins D2, D11 and D12 are also PWM). If further channels are added using a Mega2560 board, then a much larger enclosure and secondary vero-board (holding the PWM circuitry – see Appendix D) would be required. Using a cooling fan is mandatory. More channels will require a higher amperage 12VDC supply, heaver wire and possibly using 2 - 4 tracks to carry the 12V rail. Using a single copper track might cause the track to overheat and burn out.

If remote operation was more important, then the toggle switches and LCD1602+I2C could be omitted and that code removed.

The temperature probes could be connected directly onto the vero-board rather than using 3.5mm stereo connectors. The probe cable length is around 1 meter so that means the unit must be placed relatively close to the OTA’s. In my configuration, I use a side by side refractor setup and the dew controller is attached to the main dovetail bar between the two OTA’s.

When fitting the controller to the mount, It is important that the air vents and cooling fan are not obstructed.

The cooling fan should NOT be omitted. The RGB LED could be omitted. If adding extra channels, you definitely need the cooling fan. It is highly recommended to use a cooling fan.

ALTERNATIVE DHTXX SENSORS

A higher accuracy DHT21 could be used in place of the DHT11 sensor. The Arduino code already supports the sensor (user must redefine MYSENSOR to specify either DHT11 or DHT21 and then recompile and download code to the controller). No hardware changes are required to support the DHT21, DHT22 or DHT33 sensors. Simply unplug the DHT11 module and connect the DHTxx sensor using the same pin requirements (VCC, GND, DATA).

WIRING THE DS18B20 TEMPERATURE PROBES TO STEREO 3.5MM PLUGS (MALE)

post-33939-0-55198300-1410983709.jpgpost-33939-0-97898300-1410983711.jpg

Share this post


Link to post
Share on other sites

BUILDING THE CONTROLLER

Start with the enclosure. Use a Dremel tool or hobby knife to cut the air slot vents and hole for the LCD. Drill holes for mounting the LCD as well as the fuse, toggle switches and connectors (RCA, stereo, DC power).

Mount the connectors, fuse, DC power socket, toggle switches, RGB LED, LEDS and LCD as shown in the build pictures. Layout is important. Changing the location will cause problems in assembly.

Solder appropriate wire lengths (150cm or 6”) of heavy duty wire to the fuse, RCA connectors and power socket. Solder appropriate wire lengths (150cm or 6”) to the stereo sockets and toggle switches.

Mount the DHT11 sensor as indicated in the build photos and feed the connector wires back into the enclosure.

Now that the enclosure is finished, proceed to the vero board.

From this point on you do not want to make any mistakes. Trying to unsolder a component that has been placed in the wrong holes will cause major issues. Double check everything before soldering.

Start with the vero board and cut the correct tracks at the position indicated in the layout diagram by a red X and between each of the Nano pins as indicated.

Solder the header pins in place as indicated for the Nano.

Solder the jumper wires for Ground (4 green jumper wires), 12VDC (2 yellow jumper wires) and 5VDC (1 red jumper wire).

Solder the 11 resistors in place.

Solder the 1A10 diode in place. Ensure it is the correct way round before soldering.

Mount the transistors on the vero board and solder in place. Ensure that the TIP120 transistors are orientated correctly before soldering.

Solder the toggle switch wires to the vero board (PB1+ PB1- and PB2+ PB2-)

Solder the wires from the DHT11 sensor in place (DHT11 VCC, DHT11 SIG, DHT11 GND)

Solder the wires from the LCD1602/I2C in place (LCD GND, LCD 5V, LCD SCL, LCD SCA)

Solder the RGB LEDS in place (LED R, LED G, LED B, RGB GND)

Solder the PWM LEDS in place (PWM LED+, LED1-, LED2-)

(Note the PWM LED for channel 1 is wired to LED1-)

Solder the fan in place (Fan +ve, Fan –ve)

Solder the RCA connector wires in place (Top socket DS1/DS1, other socket DS2/DS2)

(It does not matter which lead is which as long as the pair of wires connects to the same, ie DS1 and DS1)

Solder the Stereo socket wires in place (socket1 tip=probe1, socket 2 tip-probe2, the other two pins wired to Probe1 VCC/GND and Probe2 VCC/GND)

(Top socket = socket1 = probe1)

For the 12VDC socket, wire the ground wire to the 12VDC GND and the +ve wire to the center of the fuse socket

Wire the other connector of the fuse socket to the +12VDC IN

                               

Perform a visual inspection looking for unsoldered leads, wires or components in the wrong place, diodes the wrong way round, transistors the wrong way round, shorted tracks and any other issues.

Mount the Nano controller

Power the Nano via micro-usb cable. The LCD should light up. The power LED on the DHT11 sensor should be on. The LED light on the Nano should light up. If the LED is off, it indicates a power issue (possibly a short) and you will need to recheck all your connections and solder joints and component placing again.

The backlight of the LCD might need to be adjusted.

Now run each of the test programs to verify operation.

Note: The author does NOT provide debugging support in the event that your build is non-operational.  

Share this post


Link to post
Share on other sites

Arduino Code Release

eepromanything.h

#include <EEPROM.h>
#include <Arduino.h>  // for type definitions
template <class T> int EEPROM_writeAnything(int ee, const T& value)
{
    const byte* p = (const byte*)(const void*)&value;
    unsigned int i;
    for (i = 0; i < sizeof(value); i++)
          EEPROM.write(ee++, *p++);
    return i;
}
template <class T> int EEPROM_readAnything(int ee, T& value)
{
    byte* p = (byte*)(void*)&value;
    unsigned int i;
    for (i = 0; i < sizeof(value); i++)
          *p++ = EEPROM.read(ee++);
    return i;
}

Share this post


Link to post
Share on other sites

dht files

//
//    FILE: dht.h
//  AUTHOR: Rob Tillaart
// VERSION: 0.1.13
// PURPOSE: DHT Temperature & Humidity Sensor library for Arduino
//
// HISTORY:
// see dht.cpp file
//
#ifndef dht_h
#define dht_h
#if ARDUINO < 100
#include <WProgram.h>
#else
#include <Arduino.h>
#endif
#define DHT_LIB_VERSION "0.1.13"
#define DHTLIB_OK                0
#define DHTLIB_ERROR_CHECKSUM   -1
#define DHTLIB_ERROR_TIMEOUT    -2
#define DHTLIB_INVALID_VALUE    -999
#define DHTLIB_DHT11_WAKEUP     18
#define DHTLIB_DHT_WAKEUP       1
// max timeout is 100usec.
// For a 16Mhz proc that is max 1600 clock cycles
// loops using TIMEOUT use at least 4 clock cycli
// so 100 us takes max 400 loops
// so by dividing F_CPU by 40000 we "fail" as fast as possible
#define DHTLIB_TIMEOUT (F_CPU/40000)
class dht
{
public:
    // return values:
    // DHTLIB_OK
    // DHTLIB_ERROR_CHECKSUM
    // DHTLIB_ERROR_TIMEOUT
    int read11(uint8_t pin);
    int read(uint8_t pin);
    inline int read21(uint8_t pin) { return read(pin); };
    inline int read22(uint8_t pin) { return read(pin); };
    inline int read33(uint8_t pin) { return read(pin); };
    inline int read44(uint8_t pin) { return read(pin); };
    double humidity;
    double temperature;
private:
    uint8_t bits[5];  // buffer to receive data
    int _readSensor(uint8_t pin, uint8_t wakeupDelay);
};
#endif
//
// END OF FILE
//
//
//    FILE: dht.cpp
//  AUTHOR: Rob Tillaart
// VERSION: 0.1.13
// PURPOSE: DHT Temperature & Humidity Sensor library for Arduino
//
// HISTORY:
// 0.1.13 fix negative temperature
// 0.1.12 support DHT33 and DHT44 initial version
// 0.1.11 renamed DHTLIB_TIMEOUT
// 0.1.10 optimized faster WAKEUP + TIMEOUT
// 0.1.09 optimize size: timeout check + use of mask
// 0.1.08 added formula for timeout based upon clockspeed
// 0.1.07 added support for DHT21
// 0.1.06 minimize footprint (2012-12-27)
// 0.1.05 fixed negative temperature bug (thanks to Roseman)
// 0.1.04 improved readability of code using DHTLIB_OK in code
// 0.1.03 added error values for temp and humidity when read failed
// 0.1.02 added error codes
// 0.1.01 added support for Arduino 1.0, fixed typos (31/12/2011)
// 0.1.0 by Rob Tillaart (01/04/2011)
//
// inspired by DHT11 library
//
// Released to the public domain
//
#include "dht.h"
/////////////////////////////////////////////////////
//
// PUBLIC
//
// return values:
// DHTLIB_OK
// DHTLIB_ERROR_CHECKSUM
// DHTLIB_ERROR_TIMEOUT
int dht::read11(uint8_t pin)
{
    // READ VALUES
    int rv = _readSensor(pin, DHTLIB_DHT11_WAKEUP);
    if (rv != DHTLIB_OK)
    {
        humidity    = DHTLIB_INVALID_VALUE; // invalid value, or is NaN prefered?
        temperature = DHTLIB_INVALID_VALUE; // invalid value
        return rv;
    }
    // CONVERT AND STORE
    humidity    = bits[0];  // bits[1] == 0;
    temperature = bits[2];  // bits[3] == 0;
    // TEST CHECKSUM
    // bits[1] && bits[3] both 0
    uint8_t sum = bits[0] + bits[2];
    if (bits[4] != sum) return DHTLIB_ERROR_CHECKSUM;
    return DHTLIB_OK;
}
// return values:
// DHTLIB_OK
// DHTLIB_ERROR_CHECKSUM
// DHTLIB_ERROR_TIMEOUT
int dht::read(uint8_t pin)
{
    // READ VALUES
    int rv = _readSensor(pin, DHTLIB_DHT_WAKEUP);
    if (rv != DHTLIB_OK)
    {
        humidity    = DHTLIB_INVALID_VALUE;  // invalid value, or is NaN prefered?
        temperature = DHTLIB_INVALID_VALUE;  // invalid value
        return rv; // propagate error value
    }
    // CONVERT AND STORE
    humidity = word(bits[0], bits[1]) * 0.1;
    temperature = word(bits[2] & 0x7F, bits[3]) * 0.1;
    if (bits[2] & 0x80)  // negative temperature
    {
        temperature = -temperature;
    }
    // TEST CHECKSUM
    uint8_t sum = bits[0] + bits[1] + bits[2] + bits[3];
    if (bits[4] != sum)
    {
        return DHTLIB_ERROR_CHECKSUM;
    }
    return DHTLIB_OK;
}
/////////////////////////////////////////////////////
//
// PRIVATE
//
// return values:
// DHTLIB_OK
// DHTLIB_ERROR_TIMEOUT
int dht::_readSensor(uint8_t pin, uint8_t wakeupDelay)
{
    // INIT BUFFERVAR TO RECEIVE DATA
    uint8_t mask = 128;
    uint8_t idx = 0;
    // EMPTY BUFFER
    for (uint8_t i = 0; i < 5; i++) bits = 0;
 
    // REQUEST SAMPLE
    pinMode(pin, OUTPUT);
    digitalWrite(pin, LOW);
    delay(wakeupDelay);
    digitalWrite(pin, HIGH);
    delayMicroseconds(40);
    pinMode(pin, INPUT);
 
    // GET ACKNOWLEDGE or TIMEOUT
    uint16_t loopCnt = DHTLIB_TIMEOUT;
    while(digitalRead(pin) == LOW)
    {
        if (--loopCnt == 0) return DHTLIB_ERROR_TIMEOUT;
    }
 
    loopCnt = DHTLIB_TIMEOUT;
    while(digitalRead(pin) == HIGH)
    {
        if (--loopCnt == 0) return DHTLIB_ERROR_TIMEOUT;
    }
 
    // READ THE OUTPUT - 40 BITS => 5 BYTES
    for (uint8_t i = 40; i != 0; i--)
    {
        loopCnt = DHTLIB_TIMEOUT;
        while(digitalRead(pin) == LOW)
        {
            if (--loopCnt == 0) return DHTLIB_ERROR_TIMEOUT;
        }
 
        uint32_t t = micros();
 
        loopCnt = DHTLIB_TIMEOUT;
        while(digitalRead(pin) == HIGH)
        {
            if (--loopCnt == 0) return DHTLIB_ERROR_TIMEOUT;
        }
 
        if ((micros() - t) > 40)
        { 
            bits[idx] |= mask;
        }
        mask >>= 1;
        if (mask == 0)   // next byte?
        {
            mask = 128;
            idx++;
        }
    }
    pinMode(pin, OUTPUT);
    digitalWrite(pin, HIGH);
 
    return DHTLIB_OK;
}
//
// END OF FILE
//

Share this post


Link to post
Share on other sites

Arduino Source Code Part 1 (broken up because its rather large)

/* Code for an astronomy dew heater
   © RBB, August 2014
   
   x.xx_local
   
   This configured for Arduino NANO board, should run on UNO/MEGA without modification
   NOTES: DO NOT PLUG/UNPLUG ANY EXTERNAL DEVICE WHEN ARDUINO IS ON
   Always connect/disconnect temperature probes and dew straps with POWER OFF
  
  v2.53 16092014
  Initial Public Release
  
// LCD1602 Display Readout below, cycles every 2 seconds
// Ambient Temperature = AT, +xx, -xx
// Humidity = HU
// Dew Point = DP, +xx, -xx
// Tracking Mode = TM, A(mbient) or D(ew Point) or M(id Point
// FanMotor = FO = Off, F5 = 50% FF == 100% 
----------111111
0123456789012345
AT:___  HU:__%
DP:___  TM:_  Fx
// C1 = Channel 1 Temperature. +xx, -xx
// C2 = Channel 2 Temperature
// AB - ATBias value (-6, -4, -2, 0, 2, 4, 6)
// - a value that can be used to correct ambient temp reading from DHT11
// P1 = Channe1 1 power (00, 25, 50, 75, 100)
// P2 = Channel 2 power
----------111111
0123456789012345
C1:___  C2:___ AB
P1:___  P2:___
*/
#include <Arduino.h>
#include <avr/pgmspace.h>
#include <EEPROM.h>                   // needed for EEPROM
#include "eepromanything.h"           // needed for EEPROM
#include <Wire.h>                     // needed for I2C
#include <LiquidCrystal_I2C1602.h>    // needed for LCD1602-I2C
#include <math.h>                     // needed for dew point calculations
#include "dht.h"                      // needed for DHTxx sensor
#include <OneWire.h>                  // needed for DS18B20 temperature probe
#include <DallasTemperature.h>        // needed for DS18B20 temperature probe
// define cooling fan abd RGB LED connections for Cooling Fan indicator
#define FanMotor 5    // pwm output controls 12vdc cooling fan
#define rled 3
#define gled 6
#define bled 11
// define dhtxx sensor and temperature probe connections
#define dhtdata  4     // DHT11/21 sensor connected to pin 4
#define DELAYTIME 2000 // 2 second loop delay time, DHT11=1000, DHT21/22=2000
#define ch1temp 7      // channel 1 and 2 temperature probe on pin 7 and 8, use 4.7k pullup
#define ch2temp 8      // 
// define objects for temperature probes
OneWire oneWirech1(ch1temp);        // setup temperature probe 1
OneWire oneWirech2(ch2temp);        // setup temperature probe 2
// Pass our oneWire reference to Dallas Temperature library
DallasTemperature sensor1(&oneWirech1); // probe ch1
DallasTemperature sensor2(&oneWirech2); // probe ch1
// DB18B20 info
#define MaxProbes 2           // maximum probes per channel, really only supports 1
#define TEMP_PRECISION 10     // Set the DS18B20s precision (10bit = 0.25degrees) 
DeviceAddress tpAddress;      // used to send precision setting to specific sensor
int tprobe1 = 0;              // these indicate if there is a probe attached to that channel
int tprobe2 = 0;
// define dew channel pwm connections
#define ch1dew 9      // channel 1 dew strap pwm output
#define ch2dew 10     // channel 2 dew strap pwm output
// define modes of operation
#define NORMAL 1      // mode of operation, changed by PB switches PB1 and PB2
#define OVERRIDE 2    // or serial commands n and 1, 2
//define tracking modes and offset limits for temperature band range
#define AMBIENT 1         // constants for tracking mode algorithm, track ambient
#define DEWPOINT 2        // track dewpoint
#define HALFWAY 3         // track half way between dew point and ambient
#define OFFSETPOSLIMIT 4  // these are limits for the offset applied to 
#define OFFSETNEGLIMIT -4 // the temp calc routine for pwr to the dew straps
#define CELCIUS 1         // these used to determine display temperature values in C
#define FAHRENHEIT 2      // or F
// define LCD supported types
#define LCD1602  1        // support for two different LCD types 16 character by 2 line
#define LCD2004  2        // or 20 character by 4 line 
#define MYLCDTYPE  LCD1602  // set for the 16x2 display, if using 20x4 then change
#ifdef MYLCDTYPE = LCD1602  // determine which lcd to configure based on MYLCDTYPE
LiquidCrystal_I2C lcd(0x27, 16, 2); // address 0x27, 16 characters by 2 rows
#else
LiquidCrystal_I2C lcd(0x27, 20, 4); // address 0x27, 20 characters by 4 rows
#endif
// define DHTxx sensor supported types
#define DHT11  1          // defines for each sensor type that is supported
#define DHT21  2
#define DHT22  3
#define DHT33  4
#define MYSENSOR DHT11    // the sensor I am using is DHT11, if using DHT21 change this!!!
// define objects for sensorss
dht mydht;                // setup dhtxx sensor
int dhtchk;               // variable to hold result of reading sensor
// use voltage divider network for two push button switches using A0
// use software debouncing
#define ToggleSwPin  A0     // Toggle switches wired to A0 via resistor divider network
#define BUTTONDELAY 20      // for debounce
long buttonLastChecked = 0; // variable to limit the button getting checked every cycle
int PBVal=0;                // holds state of toggle switch read 
// defines for progmem, allows printing of progmem strings
#define MAX_STRING 30
char stringBuffer[MAX_STRING];
char* getString(const char* str) {
strcpy_P(stringBuffer, (char*)str);
return stringBuffer;
}
// variables used by controller
float ch1tempval, ch2tempval;  // temperature value for each probe
int ch1pwrval, ch2pwrval;      // percentage power to each channel
int opmode = NORMAL;           // program operation mode
int hval;                      // relative humidity from DHTxx sensor
float tval;                    // ambient temperature value from DHTxx sensor
float dew_point;               // dewpoint
char recbuff[6] = "     ";     // receive buffer for serial command strings
int ch1override, ch2override;  // used in remote mode to override channels to 100%
int cmdoch1;                   // if 1 indicates rs232 command to override power
int cmdoch2;                   // if 1 indicates rs232 command to override power
int DisplayMode = CELCIUS;     // default display temp values in Celcius
float TempF;                   // used to hold conversion of temperatures to Fahrenheit
// these strings are const PROGMEM - saves memory as its used more than once
const char PROGMEM dashline[] = "------------------------";  
const char PROGMEM normalmodestr[] = "Normal Mode";
const char PROGMEM overridemodestr[] = "Override Mode";
const char PROGMEM probesstr[] = "Probes=";
const char PROGMEM fanstr[] = "Fan=";
const char PROGMEM offsetstr[] = "Offset=";
const char PROGMEM atstr[] = "AT:";
const char PROGMEM hustr[] = "HU:";
const char PROGMEM dpstr[] = "DP:";
const char PROGMEM c1str[] = "C1:";
const char PROGMEM c2str[] = "C2:";
const char PROGMEM p1str[] = "P1:";
const char PROGMEM p2str[] = "P2:";
const char PROGMEM tmstr[] = "TM:";
const char PROGMEM atbiasstr[] = "ATBias ";
const char PROGMEM copyrightstr[] = "©RBB v2.52loc";
const char PROGMEM titlestr[] = "Dew Control";
const char PROGMEM commastr[] = ", ";
const char PROGMEM tnullstr[] = "--";
const char PROGMEM percentstr[] = "%, ";
const char PROGMEM trackstr[] = "Track: ";
const char PROGMEM fullpower[] = "100% ";
// these are stored in EEPROM - all variables in a structure
struct config_t {
          int validdata;       // if this is 99 then data is valid
          int TrackingState;   // algorithm to use is dew point temperature tracking
          // offset value used to alter temperature boundaries in algorithm
          // for determining when to apply power to dewstraps
          int offsetval;
 int fanspeed;        // speed of cooling fan
 int ATBias;          // ambient temperature bias offset
} dewconfig;
// read the toggle switches and return state of switches
// 1 = SW1 ON AND SW2 OFF, 2 = SW2 ON AND SW1 OFF, 3 = SW1 ON and SW2 ON, 0 = OFF
int readtoggleswitches(int pinNum) {
  //  sw1 (681) 650-720, sw2 (338) 310-380, sw1 and sw2 (509) 460-530  
  int val = 0;                     // variable to store the read value
  digitalWrite((14+pinNum), HIGH); // enable 20k internal pullup
  val = analogRead(pinNum);        // read the input pin
  if ( val >= 650 && val <=720 ) { 
      return 1;                    // toggle sw1 ON and SW2 OFF
  }
  else if ( val >= 460 && val <= 530 ) { 
      return 3;                    // toggle sw1 and sw2 ON
  }
  else if ( val >= 310 && val <= 380 ) {
      return 2;                    // toggle sw2 ON and SW1 OFF
  }    
  else return 0;                   // switches are OFF
}
void setup() {
  pinMode( ch1dew, OUTPUT );        // enable pwm outputs for dew straps
  pinMode( ch2dew, OUTPUT );
  pinMode( FanMotor, OUTPUT );      // enable pwm output for 12vdc fan
  // setup the RGB LEDS for the cooling fan
  pinMode( rled, OUTPUT );
  pinMode( gled, OUTPUT );
  pinMode( bled, OUTPUT );
  // read stored data from EEPROM
  EEPROM_readAnything(0, dewconfig);
  // check to see if the data is valid
  if( dewconfig.validdata != 99 ) {
     // data was erased so write some default values
     dewconfig.validdata = 99;
     dewconfig.TrackingState = DEWPOINT;  // tracking mode is dewpoint
     dewconfig.offsetval = 0;             // offset is 0
     dewconfig.fanspeed = 0;              // fan is off
     dewconfig.ATBias = 0;                // ambient temp offset is 0
     // now write the data to EEPROM
     EEPROM_writeAnything(0, dewconfig);    // update values in EEPROM
  }  
  
  // set power to dew straps to 0 and write to dew straps. set fan speed
  ch1pwrval = 0;
  ch1pwrval = 0;
  cmdoch1 = 0;            // if 1 indicates rs232 command to override power in effect
  cmdoch2 = 0;            // if 1 indicates rs232 command to override power in effect
  analogWrite( ch1dew, ch1pwrval );    // set pwm pwr for channel 1 to 0
  analogWrite( ch2dew, ch2pwrval );    // set pwm pwr for channel 1 to 0
  updatefanmotor();                    // set pwm pwr for cooling fan and RGB LEDa
  Serial.begin(57600);    // initialise serial port, now same rate as other version
  recbuff[0] = '\0';      // clear the receive buffer
  lcd.init();             // initialise the lcd display
  lcd.backlight();        // enable the backlight
  // print the title of program and copyright message to lcd
  lcd.print(getString(titlestr));
  Serial.print(getString(titlestr));
  Serial.println(getString(copyrightstr));
  lcd.setCursor( 0, 1 );  // col, row
  lcd.print(getString(copyrightstr));
  delay(DELAYTIME);
  // start temperature sensors DS18B20
  tprobe1 = 0;        // set both probe indicators NOT FOUND
  tprobe2 = 0;
  sensor1.begin();    // start the temperature sensor1
  sensor1.getDeviceCount();    // should return 1 if probe connected
  for (int i = 0; i < MaxProbes; i++) {  // look for probes
    // Search the wire for address
    if (sensor1.getAddress(tpAddress, i)) { // found?
      tprobe1 = 1;  // there is a probe1
      sensor1.setResolution(tpAddress, TEMP_PRECISION);
      // set the resolution for that probe to 10bit 0.25degC 
    }
  }
  // repeat for channel 2 probe
  sensor2.begin();
  sensor2.getDeviceCount();    // should return 1 if probe connected
  for (int i = 0; i < MaxProbes; i++) {
    // Search the wire for address
    if (sensor2.getAddress(tpAddress, i)) { // found?
      tprobe2 = 1;  // there is a probe2
      sensor2.setResolution(tpAddress, TEMP_PRECISION);
    }
  }
  
  if( MYLCDTYPE == LCD1602 ) {
    lcd.clear();
    lcd.setCursor( 0, 0 );
  }
  else {      // assume its LCD2004
    lcd.setCursor( 0, 2 );
  }
  lcd.print(getString(probesstr));    // print the number of temperature probes
  lcd.print(tprobe1+tprobe2);
  Serial.print(getString(probesstr));
  Serial.println(tprobe1+tprobe2);
  delay(DELAYTIME);
  ch1override = 0;           // set override for ch1/ch2 to off
  ch2override = 0;
}  // end of setup()

Share this post


Link to post
Share on other sites

Arduino Source Code Part 2

void loop() {
  while ( Serial.available() > 0 ) {   // there is a command rec'd from serial port
    int pos = 0;                       // index position into receive buffer
    char rec = Serial.read();          // read a char from serial port buffer
    if ( rec == '\n' ) {               // end of command string?
      processcmd();                    // then process the command
      recbuff[0] = '\0';               // clear command buffer
      Serial.flush();                  // ensire serial buffer is empty
    }
    else {
      if ( pos < 6 ) {                 // make sure we do not overfill the receive buffer
        recbuff[pos] = rec;            // add char to recbuff and build up command string
        pos++;
      }
      else {
        Serial.flush();                // flush the buffer, ignore the command if too long
      }
    }
  } // end while
  // check toggle switches for override
  PBVal = 0;
  if( buttonLastChecked == 0 ) // see if this is the first time checking the buttons
    buttonLastChecked = millis()+BUTTONDELAY;         // force a check this cycle
  if( millis() - buttonLastChecked > BUTTONDELAY ) {  // make sure a reasonable delay passed
    PBVal = readtoggleswitches(ToggleSwPin);          // read the toggle switches
    buttonLastChecked = millis();                     // reset the lastChecked value
  }
  switch( PBVal ) {
    case 0:                        // toggle sw1 and sw2 are OFF
       // need to check though if manual override command was in effect
       // if so, can only be cancelled by sending 'n' command
       if( cmdoch1 == 0 ) {
         ch1override = 0;          // disable channel override and
         ch1pwrval = 0;            // set pwm pwr to 0
         // note ch1pwrval and ch2pwrval will be updated later in the loop()
       }
       if( cmdoch2 == 0 ) {
         ch2override = 0;          // disable channel override and
         ch2pwrval = 0;            // set pwm pwr to 0
         // note ch1pwrval and ch2pwrval will be updated later in the loop()
       }
       break;
    case 1:                        // toggle sw1 is ON and 2 is off
      if( ch1override != 1 ) {     // check to see if override already on
        if( tprobe1 == 1 ) {       // if there is a probe1
          ch1override = 1;         // set ch1 to override
          ch1pwrval = 100;         // set pwm pwr to 100%
          Serial.println("Override CH1 100% ON");
        }
      }
      if( cmdoch2 == 0 ) {
         ch2override = 0;          // disable channel override and
         ch2pwrval = 0;            // set pwm pwr to 0
         // note ch1pwrval and ch2pwrval will be updated later in the loop()
      }
      break;
    case 2:                        // toggle sw2 is ON and SW1 is OFF
      if( ch2override != 1 ) {     // check to see if override already on
        if( tprobe2 == 1 ) {       // if there is a probe1
          ch2override = 1;         // set ch1 to override
          ch2pwrval = 100;         // set pwm pwr to 100%
          Serial.println("Override CH2 100% ON");
        }
      }
      if( cmdoch1 == 0 ) {
         ch1override = 0;          // disable channel override and
         ch1pwrval = 0;            // set pwm pwr to 0
         // note ch1pwrval and ch2pwrval will be updated later in the loop()
      }
      break;
    case 3:                        // toggle sw1 and sw2 are ON
      if( ch1override != 1 ) {     // check to see if override already on
        if( tprobe1 == 1 ) {       // if there is a probe1
          ch1override = 1;         // set ch1 to override
          ch1pwrval = 100;         // set pwm pwr to 100%
          Serial.println("Override CH1 100% ON");
        }
      }
      if( ch2override != 1 ) {     // check to see if override already on
        if( tprobe2 == 1 ) {       // if there is a probe1
          ch2override = 1;         // set ch1 to override
          ch2pwrval = 100;         // set pwm pwr to 100%
          Serial.println("Override CH2 100% ON");
        }
      }
      break;
    default:                       // invalid? disable override
       ch1override = 0;            // disable channel override and
       ch1pwrval = 0;              // set pwm pwr to 0
       ch2override = 0;            // disable channel override and
       ch2pwrval = 0;              // set pwm pwr to 0
       // note ch1pwrval and ch2pwrval will be updated later in the loop()
       break;
  }
  
  // write normal or override mode to serial port monitor
  if ( ch1override == 0 && ch2override == 0) {
    opmode = NORMAL;
    Serial.print(getString(normalmodestr));
    Serial.print(getString(commastr));
  }
  else {
      Serial.print(getString(overridemodestr));
      Serial.print(getString(commastr));
  }
  
  // write tracking state to serial port monitor
  Serial.print(getString(trackstr));
  switch ( dewconfig.TrackingState ) {
    case DEWPOINT:
      Serial.print("DEWPOINT");
      break;
    case AMBIENT:
      Serial.print("AMBIENT");
      break;
    case HALFWAY:
      Serial.print("MIDPOINT");
      break;
    default:
      Serial.print("UNKNOWN");
      break;
  }
  
  // write tracking mode offset, atbias offset values to serial port monitor
  Serial.print(getString(commastr));
  Serial.print(getString(offsetstr));
  Serial.print(dewconfig.offsetval);
  Serial.print(getString(commastr));
  Serial.print(getString(atbiasstr));
  Serial.println(dewconfig.ATBias);
  
  // Read the humidity and temperature from DHTxx sensor
  if ( MYSENSOR == DHT11 ) {
    dhtchk = mydht.read11( dhtdata );
  }
  else if ( MYSENSOR == DHT21 ) {
    dhtchk = mydht.read21( dhtdata );
  }
  else if ( MYSENSOR == DHT22 ) {
    dhtchk = mydht.read22( dhtdata );
  }
  else if ( MYSENSOR == DHT33 ) {
    dhtchk = mydht.read33( dhtdata );
  }
  else dhtchk = -3; // error - undefined sensor type
  switch (dhtchk) {
    case DHTLIB_OK: // Serial.println("OK"); 
    break;
    case DHTLIB_ERROR_CHECKSUM: Serial.println("Checksum err"); break;
    case DHTLIB_ERROR_TIMEOUT: Serial.println("Timeout err"); break;
    default: Serial.println("Unknown err"); break;
  }
  if ( dhtchk == DHTLIB_OK ) {    // sensor is ok, so this is the main program now
    hval = mydht.humidity;        // read the humidity
    // Read the ambient temperature and add any calibration bias offset
    tval = mydht.temperature + dewconfig.ATBias;
    //calculate dew point
    if ( hval >= 50 )
      dew_point = dewPointFast(tval, hval);     // fast dew point RH >= 50
    else dew_point = calc_dewpoint(tval, hval); // accurate dew point RH < 50
    // print Ambient Temperature, Humidity and Dew Point to LCD
    // LCD1602 values are displayed as Integers
    // LCD2004 values are displayed to 1 decimal place
    lcd.clear();
    lcd.setCursor( 0, 0 );     // char position 0, 1st row
    if ( DisplayMode == CELCIUS ) {
      lcd.print(getString(atstr));          // ambient air temperature C
      if( MYLCDTYPE == LCD1602 ) lcd.print((int)tval, DEC); 
      else lcd.print(tval, 1);
    }
    else { // assume its Fahrenheit then
      TempF = (tval * 1.8) + 32;
      lcd.print(getString(atstr));          // ambient air temperature F
      if( MYLCDTYPE == LCD1602 ) lcd.print((int)TempF, DEC);
      else lcd.print(TempF, 1);
    }
    if( MYLCDTYPE == LCD1602 ) lcd.setCursor( 8, 0 );
    else lcd.setCursor( 10, 0);
    lcd.print(getString(hustr));           // humidity
    lcd.print(hval, DEC);
    lcd.print("%");
    lcd.setCursor( 0, 1 );     // next line
    if ( DisplayMode == CELCIUS ) {
      lcd.print(getString(dpstr));
      lcd.print(dew_point, 1);   // dew point C
    }
    else { // assume its Fahrenheit then
      TempF = (dew_point * 1.8) + 32;
      lcd.print(getString(dpstr)); // dew point F
      if( MYLCDTYPE == LCD1602 ) lcd.print((int)TempF, DEC);
      else lcd.print(TempF, 1);
    }
    
    // print tracking mode and cooling fan setting
    if( MYLCDTYPE == LCD1602 ) lcd.setCursor( 8, 1 );
    else lcd.setCursor( 10, 1);
    lcd.print(getString(tmstr));   // track mode (A)mbient (D)ew point M)id Point
    if ( dewconfig.TrackingState == AMBIENT ) lcd.print("A");
    else if ( dewconfig.TrackingState == DEWPOINT ) lcd.print("D");
    else if ( dewconfig.TrackingState == HALFWAY ) lcd.print("M");
    else lcd.print("U");      // unknown tracking mode - error
    if( MYLCDTYPE == LCD1602 ) lcd.setCursor( 14, 1 );
    else lcd.setCursor( 18, 1);
    lcd.print("F");           // FanMotor
    
    // print the fanspeed to the LCD
    if( dewconfig.fanspeed == 0 ) {
      lcd.print("0");           // 0% = OFF
    }
    else if ( dewconfig.fanspeed == 50 ) {
      lcd.print("5");    // 50%
    } 
    else if ( dewconfig.fanspeed == 75 ) {
      lcd.print("7");   // 75%
    }
    else if ( dewconfig.fanspeed == 100 ) {
      lcd.print("F");  // 100%
    }
    else lcd.print("x");                       // unknown speed - error
    // write ambient, dew point, humidity to serial port monitor
    if ( DisplayMode == CELCIUS ) {
      Serial.print(getString(atstr));          // ambient air temperature C
      Serial.print(tval, 1);                   // print AT as float .1 dec place
    }
    else { // assume its Fahrenheit then
      TempF = (tval * 1.8) + 32;
      Serial.print(getString(atstr));          // ambient air temperature F
      Serial.print(TempF, 1);                  // print AT as float .1 dec place
    }
    Serial.print(getString(commastr));
    Serial.print(getString(hustr));
    Serial.print(hval);
    if ( DisplayMode == CELCIUS ) {
      Serial.print(getString(percentstr));
      Serial.print(getString(dpstr));         // dew point C
      Serial.print(dew_point,1);              // print DP as float .1 dec place
    }
    else { // assume its Fahrenheit then
      TempF = (dew_point * 1.8) + 32;
      Serial.print(getString(percentstr));
      Serial.print(getString(dpstr));        // print DP as float .1 dec place
      Serial.print(TempF, 1);
    }
    // write tracking mode and cooling fan speed to serial port monitor
    Serial.print(getString(commastr));
    Serial.print(getString(tmstr));     
    // tracking mode, (A)mbient or (D)ew point or (M)id Point
    if ( dewconfig.TrackingState == AMBIENT ) Serial.print("A");
    else if ( dewconfig.TrackingState == DEWPOINT ) Serial.print("D");
    else if ( dewconfig.TrackingState == HALFWAY ) Serial.print("M");
    else Serial.print("U");      // unknown tracking mode - error
    // write fan speed to serial port monitor
    Serial.print(", F");           // FanMotor
    if( dewconfig.fanspeed == 0 ) Serial.println("0");         // 0% = OFF
    else if ( dewconfig.fanspeed == 50 ) Serial.println("5");  // 50%
    else if ( dewconfig.fanspeed == 75 ) Serial.println("7");  // 75%
    else if ( dewconfig.fanspeed == 100 ) Serial.println("F"); // 100%
    else Serial.println("x");       // unknown speed - error
    if( MYLCDTYPE == LCD1602 ) delay(DELAYTIME);
    // need a delay on 1602 screen as only have 2 lines and have used all lines
    // so need to clear display for next lot of information, hence need a wait time
    // else it flashes too fast
    
    // Send the command to get temperatures from DS18B20 probes
    if( tprobe1 == 1 ) sensor1.requestTemperatures();
    if( tprobe2 == 1 ) sensor2.requestTemperatures();
    delay(750 / (1 << (12 - TEMP_PRECISION))); // should be long enough to wait
    // get channel 1 temperature
    if( tprobe1 == 1 ) ch1tempval = sensor1.getTempCByIndex(0); else ch1tempval = -1.0;
    // get channel 2 temperature
    if( tprobe2 == 1 ) ch2tempval = sensor2.getTempCByIndex(0); else ch2tempval = -1.0;
    // now calculate how much power (0-100%) to apply
    // if override off then update pwm power for each channel
    // first set to 0, if probes connected they will be updated
    if( ch1override == 0 )
      if( tprobe1 != 0 ) ch1pwrval = 0; // do not change if override on
    if( ch2override == 0 )
       if( tprobe2 != 0 ) ch2pwrval = 0; // do not change if override on
    if ( tprobe1 != 0 ) 
       if ( ch1override == 0 ) ch1pwrval = getpwr( ch1tempval, dewconfig.TrackingState );
    if ( tprobe2 != 0 )
       if ( ch2override == 0 ) ch2pwrval = getpwr( ch2tempval, dewconfig.TrackingState );
    // now update the dew channels with the new pwm pwr setting 
    analogWrite( ch1dew , ch1pwrval * 2.5 );    // set the PWM value to be 0-255
    analogWrite( ch2dew , ch2pwrval * 2.5 );    // set the PWM value to be 0-255
    // update the LCD and serial displays with probe temperatures and pwm pwr settings
    if( MYLCDTYPE == LCD1602 ) {
      lcd.clear();
      lcd.home();
    }
    else lcd.setCursor( 0, 2 );
    if ( DisplayMode == CELCIUS ) {
      lcd.print(getString(c1str));    // probe1 temp C
      if( tprobe1 == 0 ) lcd.print(getString(tnullstr));
      else {
         if( MYLCDTYPE == LCD1602 ) lcd.print((int)ch1tempval);
         else lcd.print(ch1tempval, 1 );
      }
    }
    else { // assume its Fahrenheit then
      TempF = (ch1tempval * 1.8) + 32;
      lcd.print(getString(c1str));    // probe1 temp F
      if( tprobe1 == 0 ) lcd.print(getString(tnullstr)); 
      else {
        if( MYLCDTYPE == LCD1602 ) lcd.print((int)TempF, DEC);
        else lcd.print(TempF, 1);
      }
    }
    if( MYLCDTYPE == LCD1602 ) lcd.setCursor(8, 0);
    else lcd.setCursor( 10, 0 );
    if ( DisplayMode == CELCIUS ) {
      lcd.print(getString(c2str));    // probe2 temp C
      if( tprobe2 == 0 ) lcd.print(getString(tnullstr)); 
      else {
        if( MYLCDTYPE == LCD1602 ) lcd.print((int)ch2tempval);
        else lcd.print(ch2tempval, 1);
      }
    }
    else { // assume its Fahrenheit then
      TempF = (ch2tempval * 1.8) + 32;
      lcd.print(getString(c2str));    // probe1 temp F
      if( tprobe2 == 0 ) lcd.print(getString(tnullstr)); 
      else {
        if( MYLCDTYPE == LCD1602) lcd.print((int)TempF, DEC);
        else lcd.print(TempF, 1);
      }
    }
    
    // print ATBias
    if( MYLCDTYPE == LCD1602 ) lcd.setCursor(14,0); else lcd.setCursor(16,0);
    lcd.print(dewconfig.ATBias);
    if( MYLCDTYPE == LCD1602 ) lcd.setCursor(0, 1); else lcd.setCursor(0, 3);
    // print pwm pwr settings
    lcd.print(getString(p1str));
    lcd.print(ch1pwrval);  // PWM power strap 1
    lcd.print("%");
    if( MYLCDTYPE == LCD1602 ) lcd.setCursor(8, 1); else lcd.setCursor( 10, 1 );
    lcd.print(getString(p2str));      // PWM power strap 2
    lcd.print(ch2pwrval);
    lcd.print("%");
    
    // write probe temperatures to serial port monitor
    if ( DisplayMode == CELCIUS ) {
      Serial.print(getString(c1str));    // Probe 1 temp C
      if( tprobe2 == 0 ) Serial.print(getString(tnullstr)); else Serial.print(ch1tempval,1);
    }
    else { // assume its Fahrenheit then
      TempF = (ch1tempval * 1.8) + 32;
      Serial.print(getString(c1str));    // Probe 1 temp F
      if( tprobe2 == 0 ) Serial.print(getString(tnullstr)); else Serial.print(TempF, 1);
    }
    if ( DisplayMode == CELCIUS ) {
      Serial.print(getString(commastr));
      Serial.print(getString(c2str));    // Probe 2 temp C
      if( tprobe2 == 0 ) Serial.print(getString(tnullstr)); else Serial.print(ch2tempval, 1);
    }
    else { // assume its Fahrenheit then
      TempF = (ch2tempval * 1.8) + 32;
      Serial.print(getString(commastr));
      Serial.print(getString(c2str));    // Probe 1 temp F
      if( tprobe2 == 0 ) Serial.print(getString(tnullstr)); else Serial.print(TempF, 1);
    }
    
    // write pwm pwr for each channel to serial port monitor
    Serial.print(getString(commastr));
    Serial.print(getString(p1str));
    Serial.print(ch1pwrval);      // PWM power strap 1
    Serial.print(getString(percentstr));
    Serial.print(getString(p2str));
    Serial.print(ch2pwrval);      // PWM power strap 2
    Serial.println("%");
    delay( DELAYTIME );
  }
  else {
    // do nothing as cannot read sensor
    Serial.println("Error: DHTxx");
    delay( DELAYTIME );  // ensure 2s delay between attempts at reading sensor again
  }
  lcd.clear();
  lcd.setCursor( 0, 0 );
}

Share this post


Link to post
Share on other sites

Arduino Source Code Part 3

// delta max = 0.6544 wrt dewPoint()
// 5x faster than dewPoint()
// Accurate to +-1 degree C as long as the relative humidity is above 50%
double dewPointFast(double celsius, double humidity) {
  double a = 17.271;
  double b = 237.7;
  double temp = (a * celsius) / (b + celsius) + log(humidity / 100);
  double Td = (b * temp) / (a - temp);
  return Td;
}
// calculates dew point
// input:   humidity [%RH], temperature in C
// output:  dew point in C
// use this where RH is < 50%
float calc_dewpoint(float t, float h) {
  float logEx, dew_point;
  logEx = 0.66077 + 7.5 * t / (237.3 + t) + (log10(h) - 2);
  dew_point = (logEx - 0.66077) * 237.3 / (0.66077 + 7.5 - logEx);
  return dew_point;
}
int getpwr( float channeltemp, int trackmode ) {
  int pwrlevel = 0;
  
  if ( tprobe1 == 0 ) return 0;  // if a probe is not present, do not set a pwr level
  if ( tprobe2 == 0 ) return 0;  // if a probe is not present, do not set a pwr level
  
  if ( trackmode == DEWPOINT ) {
    if ( channeltemp >= (dew_point + 6.0 + dewconfig.offsetval) ) {
      pwrlevel = 0;
    }
    else if ( channeltemp >= (dew_point + 5.0 + dewconfig.offsetval) ) {
      pwrlevel = 10;
    }
    else if ( channeltemp >= (dew_point + 4.0 + dewconfig.offsetval) ) {
      pwrlevel = 20;
    }
    else if ( channeltemp >= (dew_point + 3.0 + dewconfig.offsetval) ) {
      pwrlevel = 50;
    }
    else if ( channeltemp >= (dew_point + 2.0 + dewconfig.offsetval) ) {
      pwrlevel = 75;
    }
    else pwrlevel = 100;
  }
  else if ( trackmode == AMBIENT) {    // assume trackmode is AMBIENT
    if ( channeltemp <= (tval - 9.0 + dewconfig.offsetval) ) {          
      // is the OTA temperature way below ambient
      pwrlevel = 100;                         // then set the pwr level to 100%
    }
    else if ( channeltemp <= (tval - 7.0 + dewconfig.offsetval) ) {     
      // is the OTA temperature 7 degrees or less below ambient
      pwrlevel = 75;                         // then set the pwr level to 75%
    }
    else if ( channeltemp <= (tval - 5.0 + dewconfig.offsetval) ) {     
      // is the OTA temperature 5 degrees or less below ambient
      pwrlevel = 50;                         // then set the pwr level to 50%
    }
    else if ( channeltemp <= (tval - 3.0 + dewconfig.offsetval) ) {     
      // is the OTA temperature 3 degrees or less below ambient
      pwrlevel = 20;                         // then set the pwr level to 20%
    }
    else if ( channeltemp <= (tval - 1.0 + dewconfig.offsetval) ) {     
      // is the OTA temperature 1 degrees or less below ambient
      pwrlevel = 10;                         // then set the pwr level to 10%
    }
    else pwrlevel = 0;                       
    // if ota close to ambient then pwr level to 0%
  } // end of if trackmode
  else if ( trackmode == HALFWAY) {    // assume trackmode is MIDPOINT
    if ( channeltemp >= (tval - (((tval - (int)dew_point) / 2) - 0) + dewconfig.offsetval)) {
      pwrlevel = 0;
    }
    else if ( channeltemp >= (tval - (((tval - (int)dew_point) / 2) - 2) + dewconfig.offsetval)) {
      pwrlevel = 20;
    }
    else if ( channeltemp >= (tval - (((tval - (int)dew_point) / 2) - 4) + dewconfig.offsetval)) {
      pwrlevel = 50;
    }
    else if ( channeltemp >= (tval - (((tval - (int)dew_point) / 2) - 6) + dewconfig.offsetval)) {
      pwrlevel = 100;
    }
    else pwrlevel = 100; // its lower than midpoint - 7
  } // end of if trackmode
  else pwrlevel = 0;       // set pwrlevel to 0 if there is an unknown tracking mode
  return pwrlevel;
}
void updatefanmotor() {
  if( dewconfig.fanspeed == 100 ) {
    analogWrite( FanMotor , dewconfig.fanspeed * 2.5 );    // set the PWM value to be 100%
    analogWrite( rled, 255);
    analogWrite( gled, 0 );
    analogWrite( bled, 0 );
  }
  else if ( dewconfig.fanspeed == 0 ) {
    analogWrite( FanMotor, 0 );                  // turn fan off
    analogWrite( rled, 0 );
    analogWrite( gled, 0 );
    analogWrite( bled, 0 );
  }
  else if ( dewconfig.fanspeed == 50 ) {
    analogWrite( FanMotor, dewconfig.fanspeed * 2.5 );     // turn fan 50%
    analogWrite( rled, 0 );
    analogWrite( gled, 0 );
    analogWrite( bled, 255);
  }
  else if ( dewconfig.fanspeed == 75 ) {
    analogWrite( FanMotor, dewconfig.fanspeed * 2.5 );     // turn fan 75%
    analogWrite( rled, 0 );
    analogWrite( gled, 255);
    analogWrite( bled, 0 );
  }
}

Share this post


Link to post
Share on other sites

Arduino Source Code Part 4

void processcmd( ) {
  char ch;
  int pos = 0;
  Serial.println();
  Serial.println(getString(dashline));
  ch = recbuff[0];      // start at beginning of receive buffer
  // skip leading spaces if there are any
  while ( (ch == ' ') && (recbuff[pos] != '\0') && (pos < 6) ) {  
    pos++;
  }
  switch ( ch ) {
    case 'h' :          // display list of commands
      Serial.print(getString(titlestr));
      Serial.println(getString(copyrightstr));
      if ( dewconfig.TrackingState == DEWPOINT ) {
        Serial.print(getString(trackstr)); Serial.println("DP");
      }
      else if ( dewconfig.TrackingState == AMBIENT ) {
        Serial.print(getString(trackstr)); Serial.println("Ambient");
      }
      else if ( dewconfig.TrackingState == HALFWAY ) {
        Serial.print(getString(trackstr)); Serial.println("MidPoint");
      }
      else {
        Serial.print(getString(trackstr)); Serial.println("Unknown"); // error
      }
      if ( opmode == NORMAL ) {
        Serial.println(getString(normalmodestr));
      }
      else {
        Serial.println(getString(overridemodestr));
      }
      Serial.print(getString(offsetstr));
      Serial.println(dewconfig.offsetval);
      Serial.println("Menu");
      Serial.println("h  Help Menu");
      Serial.println("1  Override 100% pwr ch1");
      Serial.println("2  Override 100% pwr ch2");
      Serial.println("n  Normal mode");
      Serial.println("a  Track ambient");
      Serial.println("d  Track dewpoint");
      Serial.println("m  Track midpoint");
      Serial.println("c  Display Celcius (default)");
      Serial.println("f  Display Fahrenheit");
      Serial.println("<  Dec offset");
      Serial.println(">  Inc offset");
      Serial.println("z  Zero offset");
      Serial.println("0  Fan ON-100%");
      Serial.println("s  Fan OFF");
      Serial.println("5  Fan 50%");
      Serial.println("7  Fan 75%");
      Serial.print("e  "); Serial.print(getString(atbiasstr)); Serial.println("-4");
      Serial.print("r  "); Serial.print(getString(atbiasstr)); Serial.println("-3");
      Serial.print("t  "); Serial.print(getString(atbiasstr)); Serial.println("-2");
      Serial.print("y  "); Serial.print(getString(atbiasstr)); Serial.println("-1");
      Serial.print("u  "); Serial.print(getString(atbiasstr)); Serial.println("0");
      Serial.print("i  "); Serial.print(getString(atbiasstr)); Serial.println("+1");
      Serial.print("o  "); Serial.print(getString(atbiasstr)); Serial.println("+2");
      Serial.print("p  "); Serial.print(getString(atbiasstr)); Serial.println("+3");
      Serial.println("w  Save variables to EEPROM");
      Serial.println(getString(dashline));
      break;
    case '1' :              // boost 100% power to channel 1
        if( tprobe1 == 1 ) {   // only overrride if there is a probe
            if( ch1override == 0 ) { // only override if toggle sw1 off
              ch1override = 1;
              opmode = OVERRIDE;
              ch1pwrval = 100;
              cmdoch1 = 1;
              Serial.println("100% pwr Ch1");
            }
            else Serial.println("Cannot override - SW1 ON");
        }
        break;
    case '2' :              // boost 100% power to channel 2
        if( tprobe2 == 1 ) {
          if( ch2override == 0 ) {
            ch2override = 1;
            opmode = OVERRIDE;
            ch2pwrval = 100;
            cmdoch2 = 1;
            Serial.println("100% pwr Ch2");
          }
          else Serial.println("Cannot override - SW2 ON");
        }
      break;
    case 'n' :              // switch to normal mode
      opmode = NORMAL;
      ch1override = 0;
      ch2override = 0;
      cmdoch1 = 0;
      cmdoch2 = 0;
      Serial.println(getString(normalmodestr));
      break;
    case 'a' :              // switch to ambient temperature tracking
      dewconfig.TrackingState = AMBIENT;
      Serial.print(getString(trackstr)); Serial.println("AMBIENT");
      break;
    case 'd' :              // switch to dew point temperature tracking
      dewconfig.TrackingState = DEWPOINT;
      Serial.print(getString(trackstr)); Serial.println("DEWPOINT");
      break;
    case 'm' :              // switch to mid-point temperature tracking
      dewconfig.TrackingState = HALFWAY;
      Serial.print(getString(trackstr)); Serial.println("MIDPOINT");
      break;
    case 'c' :    // display in Celcius
      DisplayMode = CELCIUS;
      Serial.println("Celcius");
      break;
    case 'f' :    // diaplay in Fahrenheit
      DisplayMode = FAHRENHEIT;
      Serial.println("Fahrenheit");
      break;
    case '<' :              // decrease offset
      dewconfig.offsetval = dewconfig.offsetval - 1;
      if ( dewconfig.offsetval <= OFFSETNEGLIMIT )
        dewconfig.offsetval = OFFSETNEGLIMIT;
      Serial.print(getString(offsetstr));
      Serial.println(dewconfig.offsetval);
      break;
    case '>' :              // increase offset
      dewconfig.offsetval = dewconfig.offsetval + 1;
      if ( dewconfig.offsetval >= OFFSETPOSLIMIT )
        dewconfig.offsetval = OFFSETPOSLIMIT;
      Serial.print(getString(offsetstr));
      Serial.println(dewconfig.offsetval);
      break;
    case 'z':  // zero offset
      dewconfig.offsetval = 0;
      Serial.print(getString(offsetstr));
      Serial.println(dewconfig.offsetval);
      break;
    case '0':    // motor on 100%
      dewconfig.fanspeed = 100;
      updatefanmotor();
      Serial.print(getString(fanstr));
      Serial.println(dewconfig.fanspeed);
      break;
    case 's':    // motor OFF
      dewconfig.fanspeed = 0;
      updatefanmotor();
      Serial.print(getString(fanstr));
      Serial.println(dewconfig.fanspeed);
      break;
    case '5':    // motor on 50%
      dewconfig.fanspeed = 50;
      updatefanmotor();
      Serial.print(getString(fanstr));
      Serial.println(dewconfig.fanspeed);
      break;
    case '7':    // motor on 100%
      dewconfig.fanspeed = 75;
      updatefanmotor();
      Serial.print(getString(fanstr));
      Serial.println(dewconfig.fanspeed);
      break;
    case 'e':   // e ATBias -4
      dewconfig.ATBias = -4;
      break;
    case 'r':   // r ATBias -3
      dewconfig.ATBias = -3;
      break;
    case 't':   // t ATBias -2
      dewconfig.ATBias = -2;
      break;
    case 'y':   // y ATBias -1
      dewconfig.ATBias = -1;
      break;
    case 'u':   // u ATBias 0
      dewconfig.ATBias = 0;
      break;
    case 'i':   // i ATBias +1
      dewconfig.ATBias = 1;
      break;
    case 'o':   // o ATBias +2
      dewconfig.ATBias = 2;
      break;
    case 'p':   // p ATBias +3
      dewconfig.ATBias = 3;
      break;
    case 'w' : // write user system variables back to EEPROM
      Serial.println("Saved variables to EEPROM");
      EEPROM_writeAnything(0, dewconfig);    // update values in EEPROM
      break;    
    default:
      Serial.println(getString(dashline));
      Serial.println("Invalid cmd");
      Serial.println(getString(dashline));
      break;
  }
}

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.