Adding software features to Artemis

New things! Everything is progressing nicely. Did additional testing on the 230VAC detection circuit and wrote software to read SHT31 digital humidity/temperature sensors. Also added a ClosedLoop function so analog inputs can be used to compare to store values and have an outputs act on the comparison.

230VAC detection

Finally I had the time to properly measure the mains voltage inputs. No shorts or anything… So I decided to go on and plug in the mains voltage into the Artemis.

The 230VAC detection circuit is connected to D48 (ICP5 on the Arduino), which mean I could potentially measure the exact frequency of the mains AC voltage. Still, I do not require to have that, so instead I built a simple timer that resets if the phase comes up, and counts down if the phase disappears. This way I always have a stable reading on the signal, even when the Artemis accidentally measures on an exact phase zero crossing.

        if (digitalRead(PIN_230V_DETECT) == LOW) // Active? Reset Timer.
        {
                TIM_50HzDetect = 10;
        }
        else
        {
                if (TIM_50HzDetect) // Not active -> count 2 zero and stay.
                {
                        TIM_50HzDetect--;
                }
        }

Adding a ClosedLoop() function

So what is a closedLoop function? Well, the loop is closed meaning that Artemis measures a value, and acts on that value. It is a pretty simply piece of logic, but features make it more complex: Artemis can now use any of the analog inputs . For each of these inputs you can specify how often it should be sampled (in seconds), which channel should be used as the output, and what value should be outputted. You can specify any PWM, XPWM (the PCA9685 ouputs) or DO (Digital Output). A cool example of this is using ClosedLoop() to measure an LM35 in the aquatic water, and use a DO Relay output to activate an aquatic heater. So you basically set a target value to ClosedLoop(), and it will switch the heater on and off to maintain exactly that value. The same could work for an air heater with an air temperature sensor. This makes it so easy to vary temperatures depending on the “weather” or the time of day!

void ANA_ClosedLoop(unsigned char Channel)
{
        if (ANA_SetValues[Channel] != ANA_DISABLED)
        {
                if (Channel < PIN_NR_AD) // Internal A/D converter channel
                {
                        ANA_Values[Channel] = analogRead(Channel);
                }
                else    // SHT sensor
                {
                        // Read value. SHT sensors have 2 channels so >>1.
                        SHT_ReadSensor((Channel-PIN_NR_AD)>>1); 
                } 
                // CLOSED LOOP OFF
                if (ANA_Values[Channel] > ANA_SetValues[Channel]) 
                {
                        ANA_KillChannel(Channel);
                }
                // CLOSED LOOP ON
                if (ANA_Values[Channel] < ANA_SetValues[Channel]) 
                {
                        ANA_SetChannel(Channel);
                }
        }
}

Reading SHT31 sensors

I specifically choose the SHT31 sensor because it is I2C controlled, so no complex / blocking Arduino libraries required that do bitbanging; it is just clean and simple shooting bytes over the I2C busses.

Two SHT31 sensors that measure both temperature and relative humidity. Here both are on their own physical I2C bus.

Finally I got these working. It is a very generic implementation where you can specify up to 6 sensors that can sit on the three external I2C busses. You can program each sensor’s address and its physical I2C bus number. This allows for SHT31’s sharing a bus (it has an address line) and it allows to add different sensors later (I use the address to determine chip type).

Just when I was done, it dawned on me: I should not differentiate between analog inputs and the SHT31 sensors, and that is just what I did. When I wanted to add the SHT sensors to ClosedLoop() it became really apparent; I was getting into so much trouble duplicating code with minor changes…

So I decided to rebuild most of the SHT code. Now the SHTs deliver their values directly into “analog input values”, each sensor using two “channels” for raw temperature and raw humidity.

With that done, I was able to actually able to add the SHT31 sensor values to the ClosedLoop() functionality really easy! So now I can use both analog inputs AND the SHT31 sensor inputs for ClosedLoop() control.

void StartConversion_SHT31(unsigned char SensorNr)
{
        unsigned char i;        // Just an index var

        // First we select the proper channel
        Wire.beginTransmission(I2C_SWITCH_ADDR);
        // Select the correct channel to talk to
        Wire.write( 0x01<<(SHT_I2C_Channels[SensorNr]) ); 
        Wire.endTransmission();

        // Next we command the SHT sensor to start a conversion
        i = SHT_Addresses[SensorNr];
        Wire.beginTransmission(i);
        // Send a Medium power gather command without clock stretching
        Wire.write(0x24); 
        Wire.write(0x0b);
        Wire.endTransmission();

        // Finally we select channel0 again for regular XPWM control
        Wire.beginTransmission(I2C_SWITCH_ADDR);
        Wire.write(0x01); // Select back the PCA9685 onboard channel
        Wire.endTransmission();
}

So what remains to be done?

The only thing at this point really not working yet are the WS2812b “NeoPixel” led strips. I’ve played with the Adafruit NeoPixel Library. But I could not get it work just yet; the Artemis has a single WS2812b led on board just to display the Artemis status in RGB.

But whatever I send, the WS2812b just assumes a bright white-greenish color. So I expect timing is off somewhere and the WS2812b just sees the signal as “EVERYTHING ON”. Need to do some more debugging here, preferably I’ll just ditch the library and build it myself; I have connected the WS2812b data line to the MOSI line, so I could potentially “abuse” the Arduino’s SPI controller to create 1’s and 0’s te WS2812b understands.

Hang in for updates on the WS2812b support!

Leave a Reply

Your email address will not be published. Required fields are marked *