Determine resistor value

regpye

New Member
I want to use a rotary switch to select one of six different resistors so that I can select which program section to run by using the rotary switch.
assuming that the readadc command returns a value between 0 and 4095, and we are dividing this range into 6 equal segments to determine which program to execute based on the selected resistor.
The first resistor would be 1kΩ, the second resistor would be 2kΩ, the third resistor would be 4kΩ, the fourth resistor would be 8kΩ, the fifth resistor would be 16k and the sixth resistor would be 32kΩ.

readadc C.4,b0
if b0 < 512 then ; execute program 1
else if b0 < 1024 then ; execute program 2
else if b0 < 1536 then ; execute program 3
else if b0 < 2048 then ; execute program 4
else if b0 < 2560 then ; execute program 5
else ; execute program 6
endif

I don't know how to calculate the values of the resistors, it was only an example I have given to get the idea across.
Also I don't know what the range could be for the value of the readadc I am sure it would not be 0-4095

Has anyone used this method before and knows how to determine the calculations?
 

inglewoodpete

Senior Member
Firstly PICAXE chips only have a maximum 10-bit ADC resolution (ReadADC10 command), so you will only have a range of 0 to 1023 available.

The system will work - it is something that is commonly used in microcontroller projects. You will need to arrange the resistors as a potential divider as the ADC inputs of a PIC/PICAXE cannot determine resistance: only voltages.

When using a potential divider, the value read at the input pin of the PIC will be 1024 x R2/(R1 + R2).
 

regpye

New Member
Firstly PICAXE chips only have a maximum 10-bit ADC resolution (ReadADC10 command), so you will only have a range of 0 to 1023 available.

The system will work - it is something that is commonly used in microcontroller projects. You will need to arrange the resistors as a potential divider as the ADC inputs of a PIC/PICAXE cannot determine resistance: only voltages.

When using a potential divider, the value read at the input pin of the PIC will be 1024 x R2/(R1 + R2).
Thanks for that information, inglewoodpete

Does this look correct to you:

If you are using a voltage of 5 volts, you can adjust the resistor values to ensure that the voltage at the input pin of the PICAXE does not exceed this value.

Let's choose a fixed resistor value of 1kΩ , and use the ratio of 1:3 between each of the resistors to keep the voltage at the input pin of the PICAXE below 5 volts. Then the resistor values for each position of the rotary switch would be:

  • Position 1: R2 = 1kΩ
  • Position 2: R2 = 3kΩ
  • Position 3: R2 = 9kΩ
  • Position 4: R2 = 27kΩ
  • Position 5: R2 = 82kΩ
  • Position 6: R2 = 220kΩ
We can calculate the voltage at the input pin of the PICAXE for each position of the rotary switch:

  • Position 1: Voltage = 1024 x 1kΩ / (1kΩ + 1kΩ) = 512
  • Position 2: Voltage = 1024 x 3kΩ / (1kΩ + 3kΩ) = 768
  • Position 3: Voltage = 1024 x 9kΩ / (1kΩ + 9kΩ) = 922
  • Position 4: Voltage = 1024 x 27kΩ / (1kΩ + 27kΩ) = 976
  • Position 5: Voltage = 1024 x 82kΩ / (1kΩ + 82kΩ) = 994
  • Position 6: Voltage = 1024 x 220kΩ / (1kΩ + 220kΩ) = 998
 

marks

Senior Member
Rich (BB code):
Hi regpye,
Its common to terminate an ADCpin with a 10K ohm resistor to ground.
so R2 is always 10K

 usually each  position will switch its own series resistor from V+ picaxe supply to the common adcpin.

sw.pos     ADCvalue     nearestR1
  1          150            56K
  2          250            30K
  3          350            20K
  4          450            12K
  5          550            8.2K
  6          650            5.6K

  R1 = ReadADC10 * R2 /ADCvalue - R2
     = 1024 *10K / 650 -10K
     = 5.783K   (5.6k)

ADCvalue = R2 /(R1+R2) *1024
         = 10K / (5.6K + 10K) *1024
         = 656

We can then just divide our ReadADC10 value by 100 to give actual switch pos values
making it easy to use on menu or lookup commands
 

Jeff Haas

Senior Member
Take a look at this thread, there are a couple of good solutions there:
 

hippy

Technical Support
Staff member
It's a bit of a mystical art choosing resistors to give a maximal spread of values. For a not perfect 6-way but with fairly big jumps between each I would possibly go with -
Code:
     4K7   220R  470R  2K2   4K7
      _     _     _     _     _
5V --|_|-.-|_|-.-|_|-.-|_|-.-|_|--.  o
         |     |     |     |      `--o
         |     |     |     `---------o \
         |     |     `---------------o  o--.
         |     `---------------------o     |
         }---------------------------o    _|_ 0V
         |
         `----------------------------------> ADC
Assuming I have got my calculations right -
Code:
   rTop  rBot  vAdc  nAdc
1  4700     0  0.000    0
2  4700   220  0.224   45
3  4700   690  0.640  130
4  4700  2890  1.904  389
5  4700  7590  3.088  631
6  4700     -  5.000 1023
Code:
Select Case nAdc
  Case <  10 : Gosub Prog1
  Case <  87 : Gosub Prog2
  Case < 259 : Gosub Prog3
  Case < 510 : Gosub Prog4
  Case < 827 : Gosub Prog5
  Else       : Gosub Prog6
End Select
 

oracacle

Senior Member
I would optain the values experimentaly. Then once that was done I think giving each possible postion some hysteresis as the ADC values will flucuate for various reason such as tempurature and voltage fluctuations. Hippys' Select case example does this very well.

Essentially your wanting a voltage ladder, the ADC is fed from the tap point (think ladder rung) with the ladder going btween +v and 0v. The result of this is you should be able to use a set of uniform resistor sizes, use ohm law to work the voltage to the ADC, and thusly the theortical ADC value

V out = V in * R2 / R1+R2

Where R1 is the total value of the resitors above the tap point and R2 is the total value of the resistor below the tap point. So ig you have a string of 1k resistor the first tap position will be 1k between the ADC and power, this would mean the R1 would be 1k, while R2 would be 6k assuming a 5v power source you would have bout 4.8v going to the ADC pin.
Next position R1 = 2K, R2 = 5k, V out = 3.7

Quick spread sheet to show the theoretical output from a 7x1k voltage ladder
 

Attachments

regpye

New Member
Thanks all you guys,
As the circuit is pretty simple and the coding too, I guess the best way is to test them all out for real,
I will do that in the following days and report back my findings so we all can benefit.
I see it as an easy way to give several inputs on a single pin that could be used for many different projects besides mine.
I would optain the values experimentaly. Then once that was done I think giving each possible postion some hysteresis as the ADC values will flucuate for various reason such as tempurature and voltage fluctuations. Hippys' Select case example does this very well.

Essentially your wanting a voltage ladder, the ADC is fed from the tap point (think ladder rung) with the ladder going btween +v and 0v. The result of this is you should be able to use a set of uniform resistor sizes, use ohm law to work the voltage to the ADC, and thusly the theortical ADC value

V out = V in * R2 / R1+R2

Where R1 is the total value of the resitors above the tap point and R2 is the total value of the resistor below the tap point. So ig you have a string of 1k resistor the first tap position will be 1k between the ADC and power, this would mean the R1 would be 1k, while R2 would be 6k assuming a 5v power source you would have bout 4.8v going to the ADC pin.
Next position R1 = 2K, R2 = 5k, V out = 3.7

Quick spread sheet to show the theoretical output from a 7x1k voltage ladder
I am getting a maximum ADC reading of 255, it means that ADC is returning an 8-bit value rather than the expected 10-bit value.
I tried a few different approaches and found this one to work for me using 10K resistor ladder. (changed from 1K)

Code:
;    Filename:  rotary switch select      
;    Date:   9/04/2023         
;    File Version:  #1  
;    Written by: Reg Pye
;    Function: Select code segment by rotary switch      
;    Last Revision:
;    Target PICAXE: 14M2  
; *******************************

symbol nAdc = b0

main:
    readadc C.4, b0   ; Read ADC value into b0
    select case b0
        case 0 to 42   ; First position (0 to 42/255 of range)
            gosub prog1
        case 43 to 85  ; Second position (43/255 to 85/255 of range)
            gosub prog2
        case 86 to 128 ; Third position (86/255 to 128/255 of range)
            gosub prog3
        case 129 to 170; Fourth position (129/255 to 170/255 of range)
            gosub prog4
        case 171 to 213; Fifth position (171/255 to 213/255 of range)
            gosub prog5
        case 214 to 255; Sixth position (214/255 to end of range)
            gosub prog6
    end select
    pause 50           ; Pause for 50ms before reading ADC again
    goto main          ; Repeat indefinitely

prog1:
    ' Code for first position here
    wait 2
    return

prog2:
    ' Code for second position here
    wait 2
    return

prog3:
    ' Code for third position here
    wait 2
    return

prog4:
    ' Code for fourth position here
    wait 2
    return

prog5:
    ' Code for fifth position here
    wait 2
    return

prog6:
    ' Code for sixth position here
    wait 2
    return
But now I have another problem using a 14M2 chip, as the C.3 is the only available pin left for me to use and that one can't be used for ADC.
The other pin C.4 I am already using for an LDR and the rest of the pins are input and output all in use.
Is it possible to have a pin do duel functions or is this just a dream?
 
Last edited:

oracacle

Senior Member
You need to use readadc10 for ten bit readings. That also has to read into a word variable and not a byte
 

inglewoodpete

Senior Member
Please explain more about this, it is new to me and I am learning slowly.
Your code is using the ReadADC command and b0 as the register to receive the returned value. Both work with (provide) 8 bit data.

For the 10-bit ADC capability of the PICAXE, you need to use the ReadADC10 command and store the result in a word register (like w0 or w5 etc).

Both of these concepts are documented in the Manual 2 (command reference pdf) or on-line help. Time for some reading :).
 

regpye

New Member
Your code is using the ReadADC command and b0 as the register to receive the returned value. Both work with (provide) 8 bit data.

For the 10-bit ADC capability of the PICAXE, you need to use the ReadADC10 command and store the result in a word register (like w0 or w5 etc).

Both of these concepts are documented in the Manual 2 (command reference pdf) or on-line help. Time for some reading :).
Thanks for that, I have the books open now.
 

regpye

New Member
Thanks for that, I have the books open now.
I now have more things I don't understand.
After reading the section on ADC I am more confused.
Also after that section is Individual Pin Masking that I don't understand either, but possibly could be used to change the C.3 pin on a 14M2 chip to read ADC, is that possible and if so how do I go about it.?
 

Aries

New Member
change the C.3 pin on a 14M2 chip to read ADC, is that possible and if so how do I go about it.?
No, it is not possible. As you will see in Manual 1 (Pinout Diagrams), C.3 is an input only pin.
And, as it says in Manual 2 (adcsetup), the only use of adcsetup on M2 chips is to change back from ADC to logic.
 

regpye

New Member
No, it is not possible. As you will see in Manual 1 (Pinout Diagrams), C.3 is an input only pin.
And, as it says in Manual 2 (adcsetup), the only use of adcsetup on M2 chips is to change back from ADC to logic.
Okay, so that looks like I will have to develop a new circuit board and use an 18M , the 14m2 board is full and no more pins available.
 

Attachments

oracacle

Senior Member
Can you post an actual circuit diagram, you might just need to rearrange summer things. I'm not really in the mood for reverse engineering things ATM
 

inglewoodpete

Senior Member
Another option would be to use a 20M2 or 20X2 to replace the 14M2. Both of these 20-pin chips use to same power and programming pin layout to the 14M2. The 18M2 is an oddball chip, with its unique pin layout. These is nothing wrong with using the 18-pin chip: it just has a different pin layout.

Personally, I would use a 20X2 due to its superior capabilities (many features but particularly timer and interrupt capabilities).

I've just cast my eye over your PCB design. I notice that you a using an LM7810 off the 12 volt supply. The 7810 needs a minimum input voltage of 12.5v in order to output a regulated 10 volts. If your 12v supply is actually 12.5v or more, then you will be fine. Otherwise, choose a low dropout regulator like an LM2940T-10 or other types.
 

regpye

New Member
Another option would be to use a 20M2 or 20X2 to replace the 14M2. Both of these 20-pin chips use to same power and programming pin layout to the 14M2. The 18M2 is an oddball chip, with its unique pin layout. These is nothing wrong with using the 18-pin chip: it just has a different pin layout.

Personally, I would use a 20X2 due to its superior capabilities (many features but particularly timer and interrupt capabilities).

I've just cast my eye over your PCB design. I notice that you a using an LM7810 off the 12 volt supply. The 7810 needs a minimum input voltage of 12.5v in order to output a regulated 10 volts. If your 12v supply is actually 12.5v or more, then you will be fine. Otherwise, choose a low dropout regulator like an LM2940T-10 or other types.
The circuit works fine with the 10 volt regulator because the whole system is actually solar powered and the supply voltage is around 14+ volts off the battery. The mosfets for the pumps use the full power of the battery while the processor uses 5 volts
I had to put the 10 volt regulator in the circuit because the 5 volt regulator was shutting down. After adding the 10 volt reg all was fine.
When designing the first board I used 12 volts for testing and the circuit worked fine, but when I connected the higher voltage I found I had to reduce the power down using an expensive buck convertor, so I redesigned adding the 10 volt regulator. I am using two of these systems now with no problems but wanted to make the system better and easy to change by anyone that hasn't the programming skills or equipment to make the changes if needed.

I don't have a 20 pin chip at present, but I have a few 18 chips and I have just finished redesigning the circuit board. I decided to use a jump pin for the rotary switch instead, that way I can put the resistor ladder on the same board, but I reduced it down to 4 positions due to lack of space.
That should be still okay because I want to use it as a means of changing the programming by just changing the jumper and 4 programs should be enough. Some of these hydroponic systems use large tanks and others use small tanks, so the refilling times and also the programming times for the pumps can be selected by just changing a jumper.
I will keep in mind about the pin similarities of the 14 and 20 pin chips, that is very handy. Thanks for that tip.
 

regpye

New Member
Wow! this is getting more and more complicated.
What I wanted to do is not working.
I have start0, start1, start2 programs running simultaneously and wanted to run a prestart to them so that I could set values for those programs running, but selectable through the rotary switch code we have been working on.
I now find that start0 has to be at the beginning of the program structure and the rotary switch code I only need to run once as that sets the conditions for the other sections. I thought I could put the rotary code in start0 and rename the other sections to start1...start3 (maybe I still can) but I need to make the start0 only run at the beginning and then not repeat again until the next power up.
Need some experienced coders for this one I think, I haven't been able to find anything in the manuals yet to explain how to do it.

The rotary switching code was suppose to select the following code which would be altered for each instance of the rotary selection,
I decided to use a pin jumper to select because the setting would be semi fixed and only changed if using a different hydroponic setup.

Code:
symbol flash = 1    ;change for programs ,1,2,3
symbol F_Y_LED = B.2 ;flashing yellow led
symbol GRN_LED = B.1 ;green led software flash
symbol F_R_LED = c.0 ;reserve tank low warning
symbol NFT_pump = b.5 
symbol AIR = b.3
symbol REFILLER = b.4
symbol DayTime = 100   ; LDR reading for day time threshold
symbol day_on = 45     ; 45 minutes change for programs ,1,2,3
symbol day_off = 15     ; 15 minutes change for programs ,1,2,3
symbol night_on = 5    ; 5 minutes change for programs ,1,2,3
symbol night_off = 45     ; 45 minutes change for programs ,1,2,3
symbol filler_time = 240 ;seconds, 4 minutes = 240 ideal for IBC tank, for smaller tank say 100L use about 30 seconds change for programs ,1,2,3
The above is for the 14M2 chip but I would change it for the 18M2 chip
 

oracacle

Senior Member
Personally i would not be using start0, start1 etc. That is simple multi tasking. you are looking for something that executes different sections of code depending on a input. essentially a state machine.

Post #8 you actually have an example of pretty much how I would do it. Although I would have the code within the "select case" instead of calling a gosub (there is nothing wrong with such a function call, but it's easier for humansd to follow and debug without it). This is also where having acccess to the background timer, timer interrupt comes in very handy on the X2 controllers for what appears to be some timer functons you have going on.

I have found that more and more that i am using picaxe less these days, but using C for writing MCU code has taught me that you can often get better results with correctly structured code. Read the switch postion on every loop of the the main code, using select case on the basis of the value will mean that only the code for that postion will be executed along side whatever else you have on the main program loop. Avoiding pauses and timers can mean you get to be able to do psuedo multitaksing. increasing the clock speed normally negates any noticable lag if that become and issues (and doesn't cause issues with external factors

At this point i suggest that you post your entire code so that it can be looked at in it's entirety. I ma sure that some one here can negate any issues you are having.
 

regpye

New Member
Personally i would not be using start0, start1 etc. That is simple multi tasking. you are looking for something that executes different sections of code depending on a input. essentially a state machine.

Post #8 you actually have an example of pretty much how I would do it. Although I would have the code within the "select case" instead of calling a gosub (there is nothing wrong with such a function call, but it's easier for humansd to follow and debug without it). This is also where having acccess to the background timer, timer interrupt comes in very handy on the X2 controllers for what appears to be some timer functons you have going on.


At this point i suggest that you post your entire code so that it can be looked at in it's entirety. I ma sure that some one here can negate any issues you are having.
This code is working fine, but has to be manually changed for setting the pumping times etc. I wanted to be able to change the settings by just selecting a wired position (rotary switch or jumped pins) I am not a coder, so I have been a while developing the working code that I am happy with, but others that want my systems do not have programming skills or the needed means of changing things for their setups.
As this is just a hobby for me it doesn't matter that much to me, but I am trying to make it easier for others to use.

Code:
;NFT hydroponic controller to control water levels of tanks, running of NFT pump, refilling pump and air flow pump, change pumping times between daytime and nighttime, give warnings if main supply tank is low, indicat what function is active during use.
;coded for picaxe 14M2+ and use with an IBC as the NFT supply tank and connected to a rainwater tank for the reserve tank.
;change settings in start0 section to change the refilling time that is on after float switch toggles back. symbol filler_time.
;change settings in start1 level low section to change the pin values of NO or NC. Lines 61-62

; c.0  flashing red led hardware flash
; c.1  bulk tank sensor white leads input
; c.2  reserve tank sensor yellow leads input
; c.3  unused input only
; c.4  LDR input
; c.5  serial in programming
; b.0  sound
; b.1  flashing YELLOW LED hardware flash
; b.2  flashing GREEN LED sofware flash
; b.3  air pump
; b.4  refill pump
; b.5  nft pump
;symbol flash = 1    ;change for programs 2,3,4 [not used in this setup]

symbol F_Y_LED = B.2 ;flashing yellow led
symbol GRN_LED = B.1 ;green led software flash
symbol F_R_LED = c.0 ;reserve tank low warning
symbol NFT_pump = b.5
symbol AIR = b.3
symbol REFILLER = b.4
symbol DayTime = 100   ; LDR reading for day time threshold
symbol day_on = 45     ; 45 minutes
symbol day_off = 15     ; 15 minutes
symbol night_on = 5    ; 5 minutes
symbol night_off = 45     ; 45 minutes
symbol filler_time = 240 ;seconds, 4 minutes = 240 ideal for IBC tank, for smaller tank say 100L use about 30 seconds

start0:             ;check level of NFT tank and turn on filling if needed and indicate condition.
do
if pinC.2 = 0 then    ;float switch normally open, when closed trigger refilling
goto level_low
else
goto level_normal
endif
pause 100
loop
level_low:
high REFILLER         ;switch refil pump on
low GRN_LED         ;switch off green led while filling
high F_Y_LED         ; turn on flashing yellow LED to indicate filling
;********************************************************************
for b4 = 1 to filler_time     ; define 4 minutes in seconds CHANGE TO SUIT TANK SIZE
;********************************************************************   
pause 1000           ; wait 1 second
next b4         ;keep from turning off the refill pump so that it does not start again too soon.
goto start0

level_normal:
low REFILLER         ;switch refil pump off
low F_Y_LED         ;switch off flashing yellow led
high GRN_LED pause 90  low GRN_LED pause 120 high GRN_LED pause 280  low GRN_LED pause 2000     ;switch on green led to show level normal

goto start0

start1:            ; check reserve tank level and warn if low
;********************************************************************
if pinC.1 =1 then reserve_low ; white leads 1 for normally closed, 0 for normally open
if pinC.1 =0 then reserve_hi    ;CHANGE TO SUIT FLOAT SWITCH
;********************************************************************
reserve_hi:
low F_R_LED         ; turn off flashing red LED reserve tank normal
goto start1
 
reserve_low:
high F_R_LED         ; turn on flashing red LED reserve tank low
pause 2000
     sound 0, (119,50) ; sound warning
    pause 200
    sound 0, (119,50)
    pause 200
goto start1   

;--------------------------------------------------------------------------
start2:
b0 = 0           ; initialize b0 variable
main:
readadc C.4,b0     ; read LDR for night or day into variable b0
if b0 > 105 then Day
if b0 < 95 then nighttime
if b0 > 96 and b0 < 104 then waiting
goto done

Day:   
low NFT_pump
for b9 = 1 to day_off
pause 60000 ; wait 60 seconds
readadc C.4,b0 ; read LDR for night or day into variable b0
if b0 < 95 then nighttime
if b0 > 96 and b0 < 104 then waiting
next b9
high NFT_pump      ; turn off the pump
for b8 = 1 to night_off
pause 60000 ; wait 60 seconds
readadc C.4,b0 ; read LDR for night or day into variable b0
if b0 < 95 then nighttime
if b0 > 96 and b0 < 104 then waiting
next b8
goto main

nighttime:
high NFT_pump
for b9 = 1 to night_on
pause 60000 ; wait 60 seconds
readadc C.4,b0 ; read LDR for night or day into variable b0
if b0 > 105 then Day
if b0 > 96 and b0 < 104 then waiting       
next b9
low NFT_pump      ; turn on the pump
for b8 = 1 to night_off
pause 60000 ; wait 60 seconds
readadc C.4,b0 ; read LDR for night or day into variable b0
if b0 > 105 then Day
if b0 > 96 and b0 < 104 then waiting   
next b8
waiting:
wait 6
readadc C.4,b0 ; read LDR for night or day into variable b0
if b0 > 105 then Day
if b0 < 95 then nighttime
if b0 > 96 and b0 < 104 then waiting
goto main
done:
goto start2
;---------------------------------------------------------------------------

start3:    ; AIR control
let b1 = 0 ; initialize b0 variable
readadc C.4, b1 ; read LDR for night or day into variable b0
do
if b1 > 100 then
goto air_off
else
goto air_on
endif
loop

air_on: ; subroutine for air on and off repeating
high AIR
for b10 = 1 to 15 ; define on in minutes 15
pause 60000 ; wait 60 seconds
readadc C.4, b1 ; read LDR for night or day into variable b0
if b1 > 100 then
goto air_off
endif
next b10
low AIR ; air pump is off
for b11 = 1 to 15 ; define off in minutes 15
pause 60000 ; wait 60 seconds
readadc C.4, b1 ; read LDR for night or day into variable b0
if b1 < 100 then
goto air_on   
next b11
endif
goto start3

air_off:
low AIR
goto start3
 
Last edited:

Aries

New Member
[code}
;NFT hydroponic controller to control water levels of tanks, running of NFT pump, refilling pump and air flow pump, change pumping times between daytime and nighttime, give warnings if main supply tank is low, indicat what function is active during use.
;coded fo
This would be more readable if you used square brackets both sides of the CODE - please use EDIT to correct it
 

oracacle

Senior Member
There are two things that I noticed at first. There seem to be a lot of pauses. Pin c.1/c.2 is recieving a digital input. You can put either off those on c.3. each of those can be used as an output which would free up an add input on b.x for reading the switch position. This worked meana circuitry change, but not a need to change the controller.

This could have been sooner if you could have posted a circuit diagram. It will have a closer look at the code later.
 

oracacle

Senior Member
OK had a bit of closer look at the code, I would have done all of that in a single thread. There is a lot of waiting within each of the tasks. I am going to need to know a bit more about what each code section does. There are a few things that seem a little off to me.

Is there a reason what you wait a period of time for the tank to fill instead of just reading the sensor to dertmine if its filled?
Why do you use 2 different values for determining if it's night time?
Is it correct to assume that you are using flashing LED instead of LEDs that the controller flashes?

I have formated the code a little and added some coments and questions within, if you could take a look and tell me if that is correct
Code:
; c.0  flashing red led hardware flash
; c.1  bulk tank sensor white leads input
; c.2  reserve tank sensor yellow leads input
; c.3  unused input only
; c.4  LDR input
; c.5  serial in programming
; b.0  sound
; b.1  flashing YELLOW LED hardware flash
; b.2  flashing GREEN LED sofware flash
; b.3  air pump
; b.4  refill pump
; b.5  nft pump
;symbol flash = 1    ;change for programs 2,3,4 [not used in this setup]

symbol F_Y_LED = B.2 ;flashing yellow led
symbol GRN_LED = B.1 ;green led software flash
symbol F_R_LED = c.0 ;reserve tank low warning
symbol NFT_pump = b.5
symbol AIR = b.3
symbol REFILLER = b.4
symbol DayTime = 100   ; LDR reading for day time threshold
symbol day_on = 45     ; 45 minutes
symbol day_off = 15     ; 15 minutes
symbol night_on = 5    ; 5 minutes
symbol night_off = 45     ; 45 minutes
symbol filler_time = 240 ;seconds, 4 minutes = 240 ideal for IBC tank, for smaller tank say 100L use about 30 seconds

start0:             ;check level of NFT tank and turn on filling if needed and indicate condition.
    do
        if pinC.2 = 0 then    ;float switch normally open, when closed trigger refilling
            goto level_low
        else
            goto level_normal
        endif
        pause 100
    loop
;drop through to a subfunction that can also be called    
level_low:
    high REFILLER         ;switch refil pump on
    low GRN_LED         ;switch off green led while filling
    high F_Y_LED         ; turn on flashing yellow LED to indicate filling
;********************************************************************
    for b4 = 1 to filler_time     ; define 4 minutes in seconds CHANGE TO SUIT TANK SIZE
;********************************************************************   
        pause 1000           ; wait 1 second
    next b4         ;keep from turning off the refill pump so that it does not start again too soon.
    goto start0

level_normal:
    low REFILLER         ;switch refil pump off
    low F_Y_LED         ;switch off flashing yellow led
    high GRN_LED pause 90  low GRN_LED pause 120 high GRN_LED pause 280  low GRN_LED pause 2000     ;switch on green led to show level normal
goto start0

start1:            ; check reserve tank level and warn if low
;********************************************************************
    if pinC.1 =1 then reserve_low ; white leads 1 for normally closed, 0 for normally open
    if pinC.1 =0 then reserve_hi    ;CHANGE TO SUIT FLOAT SWITCH
;********************************************************************
;drop thought again
reserve_hi:
    low F_R_LED         ; turn off flashing red LED reserve tank normal
    goto start1
     
reserve_low:
    high F_R_LED         ; turn on flashing red LED reserve tank low
    pause 2000
    sound 0, (119,50)       ; sound warning - constantly?
    pause 200
    sound 0, (119,50)
    pause 200
    goto start1   

;--------------------------------------------------------------------------
start2:
b0 = 0           ; initialize b0 variable
main:
    readadc C.4,b0     ; read LDR for night or day into variable b0 - notice this is done a lot
    if b0 > 105 then Day
    if b0 < 95 then nighttime
    if b0 > 96 and b0 < 104 then waiting
    goto done

Day:   
    low NFT_pump
    for b9 = 1 to day_off        ;15 minute timing loop?
        pause 60000 ; wait 60 seconds
        readadc C.4,b0 ; read LDR for night or day into variable b0
        if b0 < 95 then nighttime
        if b0 > 96 and b0 < 104 then waiting
    next b9
    high NFT_pump      ; turn off the pump - switch pump on every 15 mins?
    for b8 = 1 to night_off
        pause 60000 ; wait 60 seconds
        readadc C.4,b0 ; read LDR for night or day into variable b0
        if b0 < 95 then nighttime
        if b0 > 96 and b0 < 104 then waiting
    next b8
    goto main

    nighttime:
    high NFT_pump
    for b9 = 1 to night_on
        pause 60000 ; wait 60 seconds
        readadc C.4,b0 ; read LDR for night or day into variable b0
        if b0 > 105 then Day
        if b0 > 96 and b0 < 104 then waiting       
    next b9
    low NFT_pump      ; turn on the pump
    for b8 = 1 to night_off
        pause 60000 ; wait 60 seconds
        readadc C.4,b0 ; read LDR for night or day into variable b0
        if b0 > 105 then Day
        if b0 > 96 and b0 < 104 then waiting   
    next b8
    
waiting:
    wait 6
    readadc C.4,b0 ; read LDR for night or day into variable b0
    if b0 > 105 then Day
    if b0 < 95 then nighttime
    if b0 > 96 and b0 < 104 then waiting
    goto main
    done:
    goto start2
;---------------------------------------------------------------------------

start3:    ; AIR control
    let b1 = 0 ; initialize b0 variable
    readadc C.4, b1 ; read LDR for night or day into variable b0
    do
        if b1 > 100 then        ;judging from the above section this would indicate air off at night
            goto air_off
        else
            goto air_on
        endif
    loop
'drop through again - this assumes the air is on, no need for if else
air_on: ; subroutine for air on and off repeating
    high AIR
    for b10 = 1 to 15 ; define on in minutes 15 - switch on in 15 mins, or have it on for 15mins?
        pause 60000 ; wait 60 seconds
        readadc C.4, b1 ; read LDR for night or day into variable b0
            if b1 > 100 then
            goto air_off
        endif
    next b10
    low AIR ; air pump is off
    for b11 = 1 to 15 ; define off in minutes 15
        pause 60000 ; wait 60 seconds
        readadc C.4, b1 ; read LDR for night or day into variable b0
        if b1 < 100 then
            goto air_on   
            next b11
        endif
    goto start3

air_off:
    low AIR
    goto start3
here is a preposed pin mapping to give access to an ADC for the resistor ladder and a summery of what i can figure out what each task does.
Code:
; *** New Pin assignment                    ; *** Old pin assignment
; c.0  flashing red led hardware flash            ; c.0  flashing red led hardware flash
; c.1  bulk tank sensor white leads input            ; c.1  bulk tank sensor white leads input
; c.2  nft Pump                            ; c.2  reserve tank sensor yellow leads input
; c.3  reserve tank sensor yellow leads input        ; c.3  unused input only        
; c.4  LDR input                            ; c.4  LDR input
; c.5  serial in programming                    ; c.5  serial in programming
; b.0  sound                            ; b.0  sound
; b.1  flashing YELLOW LED hardware flash            ; b.1  flashing YELLOW LED hardware flash            
; b.2  flashing GREEN LED sofware flash            ; b.2  flashing GREEN LED sofware flash
; b.3  air pump                            ; b.3  air pump
; b.4  refill pump                        ; b.4  refill pump
; b.5  resitor ladder for mode select            ; b.5  nft pump

symbol hardware_red    = c.0
symbol nft_pump        = c.2
symbol sounder        = b.0
symbol hardware_yellow    = b.1
symbol hardware_green    = b.2
symbol air_pump        = b.3
symbol refill_pump    = b.4

symbol bulk_sense        = pinc.1
symbol reseerve_sense    = pinc.3


symbol LDR            = c.4
symbol selection        = b.5


;start0
;check for reserve tank, flash hardware_yellow while filling
;about 4 mins to fill - maybe this should be done by checking tank level instead of waiting

;start1
;bulk tank check for fill level
;this can be either high or low and must be selectable (in code?)
;flashing hardware_led sound while filling, short sound at start of fillinf

;start2
;detects night and day every 60 second using LDR
;pump on during the day (set pin high for this) every 15 mins?
;pump off during the night (set pin low for this) every 15 mins?

;start3
;control of air pump
;this appears to be off during the day and on at night - day 15 minute cycles
 

regpye

New Member
Is there a reason what you wait a period of time for the tank to fill instead of just reading the sensor to dentine if its filled?
Why do you use 2 different values for determining if it's night time?
Is it correct to assume that you are using flashing LED instead of LEDs that the controller flashes?
Yes there is a very good reason for the waiting time for turning off the refilling tank. A float switch is used and when the switch triggers off when full the water level is at a point when it will very soon be too low again, so some over filling is needed. It could also be done with an additional float switch and more coding which I didn't want to do because of lack of pins available. The float switch is located well below the actual full level of the tank.
This section is the most important part of the adjustable changes needed for different systems and I think I have worked it out by using C.3 , two resistors and some jumper pins to form a simple on/off switch so one of two conditions can be selected by a jumper (an left alone forever)

Two values for nighttime, do you mean the change when using for AIR? The air pump isn't really that important to time, and I have actually changed that section on the latest version to have the air pump come on when the NFT pump is off. The reason for that was to reduce a section in the code altogether and the air pump comes on when the water stops flowing and continues aeration.

Yes I am using some hardware flashing LEDs, saves on programming, works fine, ready available and cheap. One is software flashing because I wanted to do that on that particular indicator.

I have been reading through the changes that you have suggested and will need some time to absorb the content, so I will print it all out and have a good read. Looks like I would have to redesign a new board again (5th one now ha..ha.. )
Thanks for all your time doing this, I really appreciate it, and am learning a lot from you.
 

oracacle

Senior Member
I would just modify your current one. Cut the track and solder in jumper wires. One of the normal steps that is gone through is called bread boarding where a prototype of the circuit is made up on a non permanent board and tested before committing to PCB.

In start 3 you have what appears to be the night ldr value set to 100 and in start 2 it seems to be 105.
 

regpye

New Member
here is a preposed pin mapping to give access to an ADC for the resistor ladder and a summery of what i can figure out what each task does.
Code:
; *** New Pin assignment                    ; *** Old pin assignment
; c.0  flashing red led hardware flash            ; c.0  flashing red led hardware flash
; c.1  bulk tank sensor white leads input            ; c.1  bulk tank sensor white leads input
; c.2  nft Pump                            ; c.2  reserve tank sensor yellow leads input
; c.3  reserve tank sensor yellow leads input        ; c.3  unused input only       
; c.4  LDR input                            ; c.4  LDR input
; c.5  serial in programming                    ; c.5  serial in programming
; b.0  sound                            ; b.0  sound
; b.1  flashing YELLOW LED hardware flash            ; b.1  flashing YELLOW LED hardware flash           
; b.2  flashing GREEN LED sofware flash            ; b.2  flashing GREEN LED sofware flash
; b.3  air pump                            ; b.3  air pump
; b.4  refill pump                        ; b.4  refill pump
; b.5  resitor ladder for mode select            ; b.5  nft pump

symbol hardware_red    = c.0
symbol nft_pump        = c.2
symbol sounder        = b.0
symbol hardware_yellow    = b.1
symbol hardware_green    = b.2
symbol air_pump        = b.3
symbol refill_pump    = b.4

symbol bulk_sense        = pinc.1
symbol reseerve_sense    = pinc.3


symbol LDR            = c.4
symbol selection        = b.5


;start0
;check for reserve tank, flash hardware_yellow while filling
;about 4 mins to fill - maybe this should be done by checking tank level instead of waiting

;start1
;bulk tank check for fill level
;this can be either high or low and must be selectable (in code?)

;flashing hardware_led sound while filling, short sound at start of fillinf

;start2
;detects night and day every 60 second using LDR
;pump on during the day (set pin high for this) every 15 mins?
;pump off during the night (set pin low for this) every 15 mins?
 
;start3
;control of air pump
;this appears to be off during the day and on at night - day 15 minute cycles
.
;start0
;check for reserve tank, flash hardware_yellow while filling
;about 4 mins to fill - maybe this should be done by checking tank level instead of waiting
It would mean more hardware needed as the level is not the top level but the used level.

;start1
;bulk tank check for fill level
;this can be either high or low and must be selectable (in code?)
Can be determined by the orientation of the float switch
;flashing hardware_led sound while filling, short sound at start of fillinf
Only required when the bulk tank is low and should be continuous as this is a critical condition.

;start2
;detects night and day every 60 second using LDR
;pump on during the day (set pin high for this) every 15 mins?
;pump off during the night (set pin low for this) every 15 mins?
The NFT pump has a day time cycle of off a short time and on a longer time, night time cycle is reversed, off for a longer time and on for a short time. Checking at frequent times if day or night because a sometime a long on or off time may be experienced when it should be either off or on, may be important in the hot summertime, not so much in winter.
During the day when the NFT pump is working the air pump is not needed. During the night time 15 minutes on and 15 minutes off repeating.
The reason for this is to reduce the power used as it is all powered by solar and there is no charging at night. The NFT pump causes a waterfall effect that produces aeration
;start3
;control of air pump
;this appears to be off during the day and on at night - day 15 minute cycles
Correct, I have changed this in some new code not implemented yet so that the air pump comes on every time the NFT pump is off, and removed the AIR section completely. As picaxe only allows 4 start programs I wanted to have a spare in case it was needed for using the rotary switch code. I have that newly coded on a currently working system and has been running for several days now and is working fine.
[/code]
 

regpye

New Member
I would just modify your current one. Cut the track and solder in jumper wires. One of the normal steps that is gone through is called bread boarding where a prototype of the circuit is made up on a non permanent board and tested before committing to PCB.

In start 3 you have what appears to be the night ldr value set to 100 and in start 2 it seems to be 105.
Yes you are right about testing on a current board and modifying it, I will do that.
For me breadboarding has always been a nightmare, maybe just me.
The LDR reading of air doesn't have to be as accurate as the readings for the water pump, so I was lazy and used a nominal value that works good enough. This air section I have now removed completely and am switching on the air pump when the NFT pump is off. Makes it simpler and more effective and after measuring the current used by the air pump it is very small and the solar can stand the power drain at night when it is on longer on with no problem.
 
Last edited:

oracacle

Senior Member
Ok, I will have another look at some point in the next day or so. But there really is no reason to have multiple starts. I will work with the code already posted. With a few little tricks removing the praises it's perfectly possible as well making the entire thing a lot more efficient and flexible.
 

regpye

New Member
Ok, I will have another look at some point in the next day or so. But there really is no reason to have multiple starts. I will work with the code already posted. With a few little tricks removing the praises it's perfectly possible as well making the entire thing a lot more efficient and flexible.
Thanks for that, it would be most helpful.
The reason I used multiple starts was because I couldn't work out how to do it in one set of code, maybe I will learn something from you which is most appreciated.
 

hippy

Technical Support
Staff member
I thought I could put the rotary code in start0 and rename the other sections to start1...start3 (maybe I still can) but I need to make the start0 only run at the beginning and then not repeat again until the next power up.
That is possible but, because all the tasks start simultaneously, you need to find a mechanism to prevent tasks from running before your setting has been determined.

There are basically two ways to do that. The first is to have all but 'start0' wait until some variable has been set which indicates settings are valid. And, as variables are initialised to zero at power-up and reset, they can check for a non-zero value.

This is code which doesn't wait, lets tasks run without settings being configured, which can be run under simulation -
Code:
#Picaxe 08M2
#Terminal 4800

Symbol setting = b10

Start0:
   SerTxd("Started", CR, LF)
   Pause 5000
   setting = 123
   Do
      SerTxd("Start0: Setting = ", #setting, CR, LF)
      Pause 1000
   Loop

Start1:
   Do
      SerTxd("Start1: Setting = ", #setting, CR, LF)
      Pause 1000
   Loop

Start2:
   Do
      SerTxd("Start2: Setting = ", #setting, CR, LF)
      Pause 1000
   Loop
When you run that you will see 'Start1' and 'Start2' running with 'Setting = 0' until 'start0' has set 'setting' -
Code:
Started
Start1: Setting = 0
Start2: Setting = 0
:
Start0: Setting = 123
Start1: Setting = 123
Start2: Setting = 123
The simple solution is to have 'Start1' and 'Start2' wait until 'setting is non-zero as the first thing they do -
Rich (BB code):
Start1
   Do : Loop Until setting <> 0
   Do
      SerTxd("Start1: Setting = ", #setting, CR, LF)
      Pause 1000
   Loop
When that now runs, with a 5 second delay after 'Started', 'Start1' and 'Start2' won't run until 'setting' is non-zero -
Code:
Started
Start0: Setting = 123
Start1: Setting = 123
Start2: Setting = 123
You can remove the 'Pause 5000' from 'Start0' and the behaviour will still be the same.

An alternative method is described in the next instalment.
 

hippy

Technical Support
Staff member
An alternative to having 'Start1' and 'Start2' wait on a variable is to have them suspend themselves as the first thing they do, and have 'Start0' resume those tasks once the settings have been configured -
Rich (BB code):
#Picaxe 08M2
#Terminal 4800

Symbol setting = b10

Start0:
   SerTxd("Started", CR, LF)
   Pause 5000
   setting = 123
   Resume 1
   Resume 2
   Do
      SerTxd("Start0: Setting = ", #setting, CR, LF)
      Pause 1000
   Loop

Start1:
   Suspend 1
   Do
      SerTxd("Start1: Setting = ", #setting, CR, LF)
      Pause 1000
   Loop

Start2:
   Suspend 2
   Do
      SerTxd("Start2: Setting = ", #setting, CR, LF)
      Pause 1000
   Loop
When that runs the order may no longer be 0, 1, 2 but no task will run until settings have been set -
Code:
Started
Start1: Setting = 123
Start2: Setting = 123
Start0: Setting = 123
Start1: Setting = 123
Start2: Setting = 123
You can again remove the 'Pause 5000' and the behaviour will remain the same.

The advantage of this version is it doesn't depend on the value in 'setting', you can set 'setting' to any value including zero and it will still work.
 

regpye

New Member
An alternative to having 'Start1' and 'Start2' wait on a variable is to have them suspend themselves as the first thing they do, and have 'Start0' resume those tasks once the settings have been configured
Hippy, this is very clever. I am intrigued by your knowledge.
 

oracacle

Senior Member
Ok this is my first run through after a fairly long day at work
Code:
; *** New Pin assignment                    ; *** Old pin assignment
; c.0  flashing red led hardware flash            ; c.0  flashing red led hardware flash
; c.1  bulk tank sensor white leads input            ; c.1  bulk tank sensor white leads input
; c.2  nft Pump                            ; c.2  reserve tank sensor yellow leads input
; c.3  reserve tank sensor yellow leads input        ; c.3  unused input only       
; c.4  LDR input                            ; c.4  LDR input
; c.5  serial in programming                    ; c.5  serial in programming
; b.0  sound                            ; b.0  sound
; b.1  flashing YELLOW LED hardware flash            ; b.1  flashing YELLOW LED hardware flash           
; b.2  flashing GREEN LED sofware flash            ; b.2  flashing GREEN LED sofware flash
; b.3  air pump                            ; b.3  air pump
; b.4  refill pump                        ; b.4  refill pump
; b.5  resitor ladder for mode select            ; b.5  nft pump

symbol hardware_red    = c.0
symbol nft_pump        = c.2
symbol sounder        = b.0
symbol hardware_yellow    = b.1
symbol hardware_green    = b.2
symbol air_pump        = b.3
symbol refill_pump    = b.4

symbol bulk_sense        = pinc.1
symbol reserve_sense    = pinc.3

symbol LDR            = c.4
symbol selection        = b.5

symbol true         = 1
symbol false        = 0

symbol refill_flag    = bit0        'flag to show if reserve pump has been switch on
symbol reserve_flag    = bit1        'flag for reserve pump active
symbol day_flag        = bit2        'day time flag
symbol nft_flag        = bit3        'flag for tracking nft pump status - true = on

symbol temp_word        = w2            'temp word for general use
symbol time_track        = w3
symbol refill_timer    = w4            'how long is passed since refill started
symbol ldr_timer        = b10            'ldr timer
symbol ldr_value        = b11            'store the LDR value
symbol sound_timer    = b12
symbol nft_timer        = w7
symbol air_timer        = w8

symbol refill_duration    = 240            '15 mins the amount of time for a refill to take place in second
symbol ldr_duration    = 60            'time in second between ldr checks
symbol sound_duration    = 2            'time between sound pulses
symbol day             = 105            'ldr value greater than this is day
symbol night        = 95            'ldr value less than this is night
symbol nft_day_on        = 900            '45 minutes in seconds
symbol nft_day_off    = 240            '15 minutes in seconds
symbol nft_night_on    = 300            '5 minutes in seconds
symbol nft_night_off    = 900            '45 minutes in seconds
symbol air_duration    = 900

init:
    'put your selection switch here, unless you want be able to change it while the system is running
    'then put it in the main loop below
    'set any variable defaults you want here as well
Main:   
    'if we just track changes in time and use an incremental counter we do not need to worry about timer overflow
    'overflow in each timer does not matter as each is reset at the time of acticvation
    'this should run every loop
    if time <> refill_timer then
        time_track = time        'store the last time we came here to detect change
        refill_timer = refill_timer + 1
        ldr_timer = ldr_timer + 1
        sound_timer = sound_timer + 1
        nft_timer = nft_timer + 1
        air_timer = air_timer + 1
        'ensure all timers are put here for incrmenting
    end if
   
    if ldr_timer => ldr_duration then    'we only have to read the LDR once every 60 seconds
        readadc ldr, ldr_value
        if ldr_value > day then
            day_flag = true        'we have set to day time
        else if ldr_value < night then
            day_flag = false        'we have set to night time
        end if
        ldr_timer = 0
    end if

'***everything I have writen below here can be put into gosubs and called from the main loop
'***doesn't have to run every loop if you don't want it too

;start0
;check for reserve tank, flash hardware_yellow while filling
;about 4 mins to fill - maybe this should be done by checking tank level instead of waiting   
   
    if reserve_sense = 0 and refill_flag = false then        'check for reserve low
        'if the puimp is off then switch it on
        refill_flag = true    'set the ump flag
        high refill_pump        'turn on the pump
        low hardware_green    'turn off the LED
        refill_timer = 0        'set the timer to zero
    end if
   
    if refill_flag = true and refill_timer => refill_duration then
        refill_flag = false
        low refill_pump
        high hardware_green
    end if
   
;start1
;bulk tank check for fill level
;this can be either high or low and must be selectable (in code?)
;flashing hardware_led sound while filling, short sound at start of fillinf   
   
    'switch these if you switch works the other way
   
    if reserve_sense = 1 and reserve_flag = true then
        'turn off LED and sound
        low hardware_red
        reserve_flag = false
    end if
   
    if reserve_sense = 0 and reserve_flag = false then
        'turn on led and sound
        high hardware_red
        reserve_flag = true
    end if
   
    if reserve_flag = true and sound_timer => sound_duration then
        sound sounder, (119,50)
        sound_timer = 0
    end if
   
   
;start2
;detects night and day every 60 second using LDR
;pump on during the day (set pin high for this) every 15-45mins
;pump off during the night (set pin low for this) every 5-15 mins?
   
    'flag as default is false so will default to night time
    'we dealt with the LDR in the loop earlier
   
    if day_flag = true then
        'its day time, off for short time - on for long.
        if nft_flag = true and nft_timer => nft_day_on then
            'the pump is on, so now switch it off and time met
            low nft_pump
            nft_flag = false
            nft_timer = 0            'reset the timer
        else if nft_flag = false and nft_timer => nft_day_off then
            high nft_pump
            nft_flag = false
            nft_timer = 0
        end if
    else
        'do night stuff
        if nft_flag = true and nft_timer => nft_night_on then
            low nft_pump
            nft_flag = false
            nft_timer = 0
        else if nft_flag = false and nft_timer => nft_day_off then
            low nft_pump
            nft_flag = false
            nft_timer = 0
        end if   
    end if
   

;start3
;control of air pump
;this appears to be off during the day and on at night - day 15 minute cycles   
   
    if ldr_value > day then
        'off during the day
        low air_pump
        'this will trigger every loop during the day but that doesn't really matter, can bedealt with if need be
    end if
   
    if ldr_value < night and air_timer => air_duration then
        toggle air_pump
        air_timer = 0
    end if
   
    goto main
This code is also about 100 bytes smaller than your original and does not use a single pause comand or loops (except the main loop). Each of your tasks have been reworked into less than a handfull of if statements each.
As it happens each of the pices that represent your tasks can be put into gosubs (always put a return on it) and called at anypoint.
I moved all the constants into symbols so that they are easy to update without missing any instances.
I used true and false symbol to alter the flag values in the lower bits. The flags are used to track the status of various items with the system. True represents a 1 and false represents 0
Over all the use of symbols should make the code easier to read and understand

I haven't put in the resistor ladder code as I ma not sure what you want it to do exectly.
I have left my orignal notes in place so you can see which bit does what in comparison to your original.
I haven't tested as I don't have a 14M2 or any of the other hardware you have. But the bits I have tested in the simulator appear to work as intended.

I am sure there is something i can do to improve it but need to go to bed.
 

regpye

New Member
This code is also about 100 bytes smaller than your original and does not use a single pause comand or loops (except the main loop). Each of your tasks have been reworked into less than a handfull of if statements each.
Wow! This is a totally different approach that I haven't seen before, looks very interesting. I still have a 14M2 chip left I think, so I may be able to test it out over the next few days (depending on travel and work I have to do)
Thanks for all that effort.
 

hippy

Technical Support
Staff member
Wow! This is a totally different approach that I haven't seen before, looks very interesting.
I am not convinced doing it by way of multi-tasking is inappropriate and would even argue that allowing tasks to define their own timing with PAUSE is a lot simpler to follow than having to keep track of elapsed time with a variable.

To me there's an elegance, simplicity, and more easily obtained understanding, with -
Code:
Start2:
  Do
    Toggle LED
    Pause 500
  Loop
Than -
Code:
MainLoop:
  Do
    If ledTime >= 500 Then
      Toggle LED
      ledTime = 0
    End If
    Pause 10
    ledTime = ledTime + 10
  Loop
But that's not to say the latter is wrong and, where one doesn't have multi-tasking available, one has no choice. It's always good to know how it could be done in both cases and choose whichever feels best or is preferred.

I would actually have coded the above as -
Code:
MainLoop:
  Do
    Gosub UpdateLed
    Pause LOOP_TIME_MS
  Loop

UpdateLed:
  If ledTime = 0 Then
    Toggle LED
  End If
  ledTime = ledTime + LOOP_TIME_MS // 500
  Return
I always favour a simple main loop with consecutive GOSUB, delegating complexity to subroutines and 'to hell with memory use' unless it becomes an issue.

But the main thing to takeaway is there are numerous ways to do things. And the most important is usually; does it work?

How it's actually done, how one believes it should be done, comes down to experience and practise, so don't worry too much if you aren't doing it the way others would. Especially if it doesn't fit with your current experience.

It took me some time to realise that my measure of a good program comes down to "elegance". It's what makes the science of programming also an art. If it's easy to understand, easy to debug, others can follow what's going on without understanding the detail, can see where the detail is if interested in that part, you have perhaps produced a masterpiece.

But don't waste time or fret over trying to create a masterpiece when what you want is something which works. How you do things, and what suits you best, will evolve over time. Having something which works is the driving force in keeping on that path.
 

oracacle

Senior Member
That's the idea of my code, this is how I would do it. And was designed with the idea of being able to separate it into gosubs if desired. My most recent practice of avoiding pause unless absolutely needed is what drive using time variable. The initial thought was just to use it directly but then realised that overflow could well be an issue.
The reduced size was more of a happy accident, I certainly did not set out to reduce the code size by 33%. Just something that was fast and effective.

However I think the biggest thing for the OP to take away is not so much how the code runs, but how much easier it is to read and debug with the use of symbols and more comprehensive connecting. No trying to remember it constantly look up what that number means or why it was chosen. It's right there in the name you gave it, with added bonus of being able to change all of its instances by just changing the value of the symbol.

Just a side note that code only took about 2.5 hours to write including some extra reverse engineering of the original. Didn't think that was to shabby.
 

regpye

New Member
But don't waste time or fret over trying to create a masterpiece when what you want is something which works. How you do things, and what suits you best, will evolve over time. Having something which works is the driving force in keeping on that path.
I have learnt so much form both Hippy and oracacle thanks to you both
 
Top