Updating my outputs at the right time?

Hi all,

I'm building a control system that will burst fire a Solid State Relay (SSR) for a proportion of a 2 second period. I think I am experiencing some timing difficulties because my SSR will not fire with outputs from the Arduino Nano of less than about 600 milliseconds.

At SSR output of 603ms the SSR will not fire, and at 670ms it does so only briefly (fed from dig-out pin 13, so I'm observing the on-board led).

My suspicion is that the loop() function is taking longer to update than I had hoped for, and this will only get worse as I add more code to give my system an LCD display, and etc..

I am trying to implement the good practice shown in Robin2's excellent article

https://forum.arduino.cc/index.php?topic=261445.msg1845408#msg1845408

by keeping the loop() code length short and by calling functions, however it appears that the main loop() will sit and wait for a function to finish before it continues, so I'm no better off, except that my code is getting neater!

The problem became apparent when I introduced the Dallas Temperature library to read the boiler flow temperature (brief description of the code's function is at the top of the sketch below). The dallas sensors take up to 750ms to respond when set to 12 bits resolution, much less at 10 bits, but indicative of the delay I have built into my code, and which I am keen to reduce or eliminate.

Apologies in advance; I tried to include code line numbering, but failed to copy the numbers with the code, and I have had to put my full code into an attachment to get under the 9000 character forum cap.

The aim is to update the SSR output duration (on pin 13) as close to every 2 seconds as is possible, and I am hoping for help to reduce the delays to program execution so that I can achieve this. I am a coding novice, but willing to learn, so my questions are as follows:

Q1. Would the transfer of the SSR updating code to an interrupt routine improve things? If so I'll have to read up on those...but that's all to my future benefit, so quite ready to do that.

Q2. How else might I get the output to fire the SSR reliably for durations between 20ms and 2000ms?

Q3. I have been unsuccessful in trying to introduce some hysteresis to prevent possible relay chatter at the 3kW, 6kW and 9kW levels. Given that I may have to re-write the code to calculate the SSR output duration, please will you give alternatives which don't have my code's inherant faults; ie a way of giving 0 - 100% power using burst fire, but including a variable for hysteresis both on rising and falling outputs.

Q4. Will altering the code in the manner you suggest allow me to introduce more code for LCD display driving, and etc, without upsetting the SSR timing once more?

Q5. The program presently compiles using no more than 30% of memory in my Nano. Would a faster/better microcontroller be a solution (as opposed to merely disguising the coding faults)?

Kind regards, GM

Cizek_heating_development_V3.2_NoLCD_09June2020.ino (15.7 KB)

Doing things like the display update and reading of A0 on every cycle through loop() looks to be non-optimal. There is no need for these to be done at such high frequency. If the code is off updating the LCD it can't be checking for a millis() timeout.

"maxCurrentPercent" is used only if "cycleDuration > 1999" for example. So there seems absolutely no point in doing all that work every time through loop.

What's "delay(2000);" doing in display=2???

Edit: Ignore me, I see you have commented out the lcd display routines. Sorry. Comments wrt reading of A0 are still relevant. Also for heven's sake increase your serial speed from 9600!

PWM modules or interrupts are your best choices if you really need more. These will definitely improve things if you have exhausted what you can do to improve performance of your loop code.

Although with PWM I don't think you can achieve a 2 second period. I think around 1Hz is the slowest you can achieve with that.

Also calling millis() multiple times introduces drift. If you want accuracy then get the value of millis() once per iteration of loop and do all your calculations, and update cycleTime, from that variable. At least that way you only have jitter to contend with.

600 mS sounds like an awfully long time for an SSR, what kind is it? I don't think I'd expect a mechanical relay to be that slow.

Using pin 13 may be a bad idea, the on board LED can make it behave differently to its siblings.

I suggest that you write a much simpler sketch that just turns the SSR on and off at some speed and try it at different rates. Wire up an indicator LED or some such so you can see if it is working.

Until you have that squared away, there's little point to the rest of the code for now.

  1. get rid of all the floating math and real-time division and tempurature library. You will only ever have 1024 possible values, so why go out to 32 bit precision and consume all the clock cycles. Open Excel, put in the first column, 0-1023. In subsequent columns, do all your calculations. Put the results in look-up tables(ie arrays of constant values). Then you can quickly index to the right value with the return value from analogRead().
const int CelsiusLUT[] = {Min,...,Max};
  1. If you need greater speed on the relays, you can place them all on one of the 3 ports (on the uno, B, C or D) and use direct port manipulation.

Hi,

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Can you post a link to the SSR you are using?
What is the load?

Thanks.. Tom.. :slight_smile:

Thanks for all your comments and ideas, I'll get on with it as time (no pun intended) allows.

wildbill:
600 mS sounds like an awfully long time for an SSR, what kind is it? I don't think I'd expect a mechanical relay to be that slow.

I think you misunderstood WildBill, each of the relays and the SSR are behaving correctly; the OUTPUT that drives the SSR is a time proportioned output which fires for a proportion of a 2 second period (eg 25% = 500ms ON, 1500ms OFF) The SSR reacts as quickly as it should once the dig-out signal goes high.

wildbill:
Using pin 13 may be a bad idea, the on board LED can make it behave differently to its siblings.

Point taken, though it helps to use it whilst in the development stage

wildbill:
I suggest that you write a much simpler sketch that just turns the SSR on and off at some speed and try it at different rates. Wire up an indicator LED or some such so you can see if it is working.

I have already done that, and have had a working model at each of the previous iterations of my project (ie using fixed values of process temperature). Now I am trying to move on to reading the process temperature with sensors. I have commented out much of the code relating to driving the LCD display - one small step at a time.

TomGeorge:
Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

It's the CAN bit that I find the most difficult! I have my circuit on a scrap of paper, that leap into drawing on the pc has eluded me so far, so no, unfortunately I can't!
If it helps, I have no problems with my external circuit, the relays AND the SSR all operate as they should, I think there's a fundamental error of logic within my software code that goes off and does something else when it SHOULD be turning ON the output to my SSR.

TomGeorge:
Can you post a link to the SSR you are using?
What is the load?

This I can do, it's 1PCS 24V-380V SSR-40DA 40A 3-32V DC-AC Solid State Relay Module for Arduino | eBay
though again I must stress that's not the problem area for me.
The load on the SSR will be 13A at 240vac, approx 3kW. Imagine this boiler being constructed of three 3kW heaters in a single housing, two switched ON or OFF by relays, the third being modulated 0 - 3kW using burst fire control. (I see you're experienced in Industrial Controls, so I don't expect you'll require further explanation here) :slight_smile:
In this way I can, through a combination of relay and SSR, generate any output between 0 and 9 kW.

Thank youfor your suggestions pcbbc, lots to think about; but essentially I get the impression I should generate an interrupt every time millis() clocks up 2 seconds, and that interrupt will send the new value of SSRoutput time to the output pin. I'm going to try to get the Dallas Temperature function to do its thing straight after this, giving it plenty of time to have the temperatures ready for me in good time for the next output cycle.

No one has suggested that a 'posher' microcontroller may be needed, so that's good.

I'll crack on and report back.
GM

I see, the issue is that the SSR is fast, but the Nano isn't able to command it quickly enough to get a smaller window than ~600mS. This because of other things the Nano is doing.

I expect that you can change things around to limit what happens in each iteration of loop. As I mentioned in the original thread, the DS18B20 library can be set to be asynchronous. Look for the setWaitForConversion function. You will have to manage the timing yourself of course, but that's just millis again.

Looking at your code (and as you said originally), the trouble started with the DS18B20. I expect async mode will resolve your issues sufficiently. If you need more granularity, you may want to pursue some of the other cycle saving suggestions upthread, but I think the temperature sensor is the elephant in the room :wink:

Hi,
Ops SSR.

You can just take a picture of your circuit and put it in your next post.

Have you some simple code that JUST concerns the SSR, to check that it is performing correctly?
As some of these "elcheepo" SSRs are of dubious quality and spec.
That price is not what I would pay for a good SSR. That brand has been noted for poor quality.

Tom... :slight_smile: