Am I using cognew/cogstop correctly?
I am having a problem where my second cog method (coolantPwmOut) was hanging when I it was supposed to go into lower power mode (when ina[I_KeyOn] == 0) with a waitcnt, so I decided to try and stop the cog/method when ina[I_KeyOn] == 0 and restart it when ina[I_KeyOn] == 1. Neither way is working, so I must be doing something wrong.
The method is supposed to put at a 2.3hz square wave signal that varies in duty cycle based on an adc input value. When ina[I_KeyOn] == 1, the method will hang somewhere, I'm not sure where because when I plug in the usb to serial into my laptop, it resets the prop and upon reset it works correctly and outputs the square wave signal. Is there a way to stop the prop from resetting when you plug the ftdi into a usb port on a computer? I could troubleshoot it possibly if I could stop that.
The code is attached if anyone would be kind enough to give me a critique so that I can learn.
Thank you.
The method is supposed to put at a 2.3hz square wave signal that varies in duty cycle based on an adc input value. When ina[I_KeyOn] == 1, the method will hang somewhere, I'm not sure where because when I plug in the usb to serial into my laptop, it resets the prop and upon reset it works correctly and outputs the square wave signal. Is there a way to stop the prop from resetting when you plug the ftdi into a usb port on a computer? I could troubleshoot it possibly if I could stop that.
The code is attached if anyone would be kind enough to give me a critique so that I can learn.
Thank you.


Comments
it is a specialty of me to first get an overview about a project.
and after that starting to develop a solution that is as simple as possible.
I'm not willing to debug your code as it is - to find the point where you have to insert something
from behind to re-re-reswitch a signal to get it on.
Maybe there are good reasons to code it exactly the way you coded it. But I don't know.
So please explain it to me.
Did I understand right a potentiometer is connected to the ADC (MCP3208).
You are reading in the potentiometer-position.
Depending on the potentiometer-value you are calculation the On-Time and Off-Time of the duty-cycle.
Then the pwm-signal is created through a method running in its own cog?
There is a lot more code in your examplefile which I do not understand with a quick reading.
Are there any addtional conditions that make the code around the basic thing described above nessesary?
To me the code looks pretty complicated and therefore difficult to maintain.
So my first suggestion is to strip down the code to the pure function.
If there are any addtional conditions please describe them from a functional point of view.
Like somebody that knows nothing about coding but knows exactly what a control-unit should do
example "if switch A is in position 2 do this. If switch B and switch C is in position 4 do that...."
Additonal comments:
Instead of using floating-point constants I would use integervalues.
Your constants have two digits behind the decimal point.
example
c_100FahrenheitOn = 87
So your value would be multiplied with 87 and then divided by 100. Rounding is automatically included in integerdivision
You defined constants for On and for Off
the Off-constant-value is simply 100 - OnConstantValue
you could use the expression "100 - OnConstantValue" where you are calculating with it
or if you would like to have a Off-constants on ist own
c_100FahrenheitOn = 87
c_100FahrenheitOff = 100 - c_100FahrenheitOn
this will assure that the sum is always 100
I guess that you measured the pwm-frequency.
2.3Hz is a pretty low PWM-frequency. Is there a special reason why the frequency must be that low?
to me it seems very unuasual to have such a low pwm-frequency.
What kind of thing is the receiver of this pwm-signal you are creating?
best regards
Stefan
It is reading a varistor, when I bench test I use a potentiometer, so yes it is connected to the MCP3208 and yes depending on that adc value, the PWM on/off time is calculated based on the constants. Unfortunately it is not linear, so I can't have a constant value that I can use in place of the constants list.
The only switch that matters in this case is the position of I_KeyOn.
I will try the math suggestion you've made, that sounds good to me.
The 2.3hz is out of my control, that was set by the receiving device and is a requirement. The receiver is an automotive dash.
I've never had a cog hang like that when coming out of a low power mode, maybe the lower power waitcnt was the wrong way to go about that, so I'm happy to try cogstop/cognew if that is the proper way to do that. I've never used the cogstop command before.
To remove float math, I will be doing this
I was using this
but will now use this
For onTime I was using this
but will now use this
' (((32653 * 99) = 3232647) * 10) = 32326470 onTime := ((pwmOutputHertzToClkCycles * c_70FahrenheitOn) * 10)For offTime I was using this
but will now use this
' (((32653 * 1) = 32653) * 10) = 326530
How does that look? Also, do you have any insight to why the cog/method is hanging? Is there a way to connect the terminal without having it reset the propeller altogether? Whenever I reset it, it works properly.
Attached is the code the way you suggested it should be written. I'm still unsure about the part as to whether the proper format would be to put the cog into a low power mode, or to stop it and restart it when I need it. What do you think?
I suspect the problem is in your case statement:
if (adcTHW <> 0) if (adcTHWBlock == false) [b]case -1[/b] ((adcTHW < 4096) AND (adcTHW => 3350) AND (adcTHWBlock == false)): onTime := ((pwmOutputHertzToClkCycles * c_70FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_70FahrenheitOff) * 10) ((adcTHW < 3350) AND (adcTHW => 3250) AND (adcTHWBlock == false)): onTime := ((pwmOutputHertzToClkCycles * c_75FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_75FahrenheitOff) * 10)Case -1 is evaluating every one of your expressions as true.Perhaps something along the lines of:
if adcTHWBlock == false case adcTHW 4096 .. 3350: ' (((32653 * 99) = 3232647) * 10) = 32326470 onTime := ((pwmOutputHertzToClkCycles * c_70FahrenheitOn) * 10) ' (((32653 * 1) = 32653) * 10) = 326530 offTime := ((pwmOutputHertzToClkCycles * c_70FahrenheitOff) * 10) 3349 .. 3250: ' (((32653 * 98) = 3199994) * 10) = 31999940 onTime := ((pwmOutputHertzToClkCycles * c_75FahrenheitOn) * 10) ' (((32653 * 2) = 65306) * 10) = 653060 offTime := ((pwmOutputHertzToClkCycles * c_75FahrenheitOff) * 10) 3249 .. 3150: onTime := ((pwmOutputHertzToClkCycles * c_80FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_80FahrenheitOff) * 10) 3149 .. 3050: onTime := ((pwmOutputHertzToClkCycles * c_85FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_85FahrenheitOff) * 10) 3049 .. 2950: onTime := ((pwmOutputHertzToClkCycles * c_90FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_90FahrenheitOff) * 10) 2949 .. 2850: onTime := ((pwmOutputHertzToClkCycles * c_95FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_95FahrenheitOff) * 10) 2849 .. 2740: onTime := ((pwmOutputHertzToClkCycles * c_100FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_100FahrenheitOff) * 10) 2739 .. 2625: onTime := ((pwmOutputHertzToClkCycles * c_105FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_105FahrenheitOff) * 10) 2624 .. 2530: onTime := ((pwmOutputHertzToClkCycles * c_110FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_110FahrenheitOff) * 10) 2529 .. 2420: onTime := ((pwmOutputHertzToClkCycles * c_115FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_115FahrenheitOff) * 10) 2419 .. 2330: onTime := ((pwmOutputHertzToClkCycles * c_120FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_120FahrenheitOff) * 10) 2329 .. 2210: onTime := ((pwmOutputHertzToClkCycles * c_125FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_125FahrenheitOff) * 10) 2209 .. 2120: onTime := ((pwmOutputHertzToClkCycles * c_130FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_130FahrenheitOff) * 10) 2119 .. 2010: onTime := ((pwmOutputHertzToClkCycles * c_135FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_135FahrenheitOff) * 10) 2009 .. 1915: onTime := ((pwmOutputHertzToClkCycles * c_140FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_140FahrenheitOff) * 10) 1914 .. 1810: onTime := ((pwmOutputHertzToClkCycles * c_145FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_145FahrenheitOff) * 10) 1809 .. 1715: onTime := ((pwmOutputHertzToClkCycles * c_150FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_150FahrenheitOff) * 10) 1714 .. 1605: onTime := ((pwmOutputHertzToClkCycles * c_155FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_155FahrenheitOff) * 10) 1604 .. 1490: onTime := ((pwmOutputHertzToClkCycles * c_160FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_160FahrenheitOff) * 10) 1489 .. 1400: onTime := ((pwmOutputHertzToClkCycles * c_165FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_165FahrenheitOff) * 10) 1399 .. 1300: onTime := ((pwmOutputHertzToClkCycles * c_170FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_170FahrenheitOff) * 10) 1299 .. 1225: onTime := ((pwmOutputHertzToClkCycles * c_175FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_175FahrenheitOff) * 10) 1224 .. 1160: onTime := ((pwmOutputHertzToClkCycles * c_180FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_180FahrenheitOff) * 10) 1159 .. 1075: onTime := ((pwmOutputHertzToClkCycles * c_185FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_185FahrenheitOff) * 10) 1074 .. 990: onTime := ((pwmOutputHertzToClkCycles * c_190FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_190FahrenheitOff) * 10) 989 .. 910: onTime := ((pwmOutputHertzToClkCycles * c_195FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_195FahrenheitOff) * 10) 909 .. 810: onTime := ((pwmOutputHertzToClkCycles * c_200FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_200FahrenheitOff) * 10) 809 .. 710: onTime := ((pwmOutputHertzToClkCycles * c_205FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_205FahrenheitOff) * 10) 709 .. 610: onTime := ((pwmOutputHertzToClkCycles * c_210FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_210FahrenheitOff) * 10) 609 .. 510: onTime := ((pwmOutputHertzToClkCycles * c_215FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_215FahrenheitOff) * 10) 509 .. 460: onTime := ((pwmOutputHertzToClkCycles * c_220FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_220FahrenheitOff) * 10) 459 .. 410: onTime := ((pwmOutputHertzToClkCycles * c_225FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_225FahrenheitOff) * 10) 409 .. 360: onTime := ((pwmOutputHertzToClkCycles * c_230FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_230FahrenheitOff) * 10) 359 .. 310: onTime := ((pwmOutputHertzToClkCycles * c_235FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_235FahrenheitOff) * 10) 309 .. 260: onTime := ((pwmOutputHertzToClkCycles * c_240FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_240FahrenheitOff) * 10) 259 .. 210: onTime := ((pwmOutputHertzToClkCycles * c_245FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_245FahrenheitOff) * 10) 209 .. 160: onTime := ((pwmOutputHertzToClkCycles * c_250FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_250FahrenheitOff) * 10) 159 .. 10: onTime := ((pwmOutputHertzToClkCycles * c_255FahrenheitOn) * 10) offTime := ((pwmOutputHertzToClkCycles * c_255FahrenheitOff) * 10)Or perhaps even:' ... getConstant onTime := ((pwmOutputHertzToClkCycles * getConstant) * 10) offTime := ((pwmOutputHertzToClkCycles * (100 - getConstant)) * 10) ' ... PRI getConstant case adcTHW 4096 .. 3350: return c_70FahrenheitOn 3349 .. 3250: return c_75FahrenheitOn 3249 .. 3150: return c_80FahrenheitOn 3149 .. 3050: return c_85FahrenheitOn 3049 .. 2950: return c_90FahrenheitOn 2949 .. 2850: return c_95FahrenheitOn 2849 .. 2740: return c_100FahrenheitOn 2739 .. 2625: return c_105FahrenheitOn 2624 .. 2530: return c_110FahrenheitOn 2529 .. 2420: return c_115FahrenheitOn 2419 .. 2330: return c_120FahrenheitOn 2329 .. 2210: return c_125FahrenheitOn 2209 .. 2120: return c_130FahrenheitOn 2119 .. 2010: return c_135FahrenheitOn 2009 .. 1915: return c_140FahrenheitOn 1914 .. 1810: return c_145FahrenheitOn 1809 .. 1715: return c_150FahrenheitOn 1714 .. 1605: return c_155FahrenheitOn 1604 .. 1490: return c_160FahrenheitOn 1489 .. 1400: return c_165FahrenheitOn 1399 .. 1300: return c_170FahrenheitOn 1299 .. 1225: return c_175FahrenheitOn 1224 .. 1160: return c_180FahrenheitOn 1159 .. 1075: return c_185FahrenheitOn 1074 .. 990: return c_190FahrenheitOn 989 .. 910: return c_195FahrenheitOn 909 .. 810: return c_200FahrenheitOn 809 .. 710: return c_205FahrenheitOn 709 .. 610: return c_210FahrenheitOn 609 .. 510: return c_215FahrenheitOn 509 .. 460: return c_220FahrenheitOn 459 .. 410: return c_225FahrenheitOn 409 .. 360: return c_230FahrenheitOn 359 .. 310: return c_235FahrenheitOn 309 .. 260: return c_240FahrenheitOn 259 .. 210: return c_245FahrenheitOn 209 .. 160: return c_250FahrenheitOn 159 .. 10: return c_255FahrenheitOnTry making test programs to understand behaviors. Here's one that demonstrates the cognew / cogstop, as well as case.
con _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 ' use 5MHz crystal var long stack[20] long cog obj fds : "fullduplexserial" ' use Parallax Serial Terminal pub main fds.start(31,30,0,115200) waitcnt(cnt + clkfreq) cog := -1 fds.tx($00) repeat if (ina[0] == 1) if cog == -1 cog := cognew(newcog, @stack) if cog > -1 fds.str(string("Starting newcog",$09," cog ID = ")) fds.dec(cog) fds.tx($0D) else if cog <> -1 cogstop(cog) cog := -1 fds.str(string("Stopping cog",$0D)) pub newcog repeat waitcnt(cnt + clkfreq) fds.str(string("newcog running",$0D)) case -1 1 and 2 : fds.str(string("1 & 2",$0D)) 3 and 4 : fds.str(string("3 & 4",$0D)) 5 and 6 : fds.str(string("5 & 6",$0D)) 7 and 8 : fds.str(string("7 & 8",$0D)) 9 and 0 : fds.str(string("9 & 0",$0D))I have an additional question: how did you recognize the code is hanging?
did you wait for at least 54 seconds if the code was hanging? if it starts working it's a "cnt-has-ran-ahead-problem"
This means WaitCnt stops the cog completely until the expression-value matches the actual cnt-value. if cnt as already ahead of the expression
it will take 54 seconds until the next match.
There is a minimum of 385 clockticks which SPIN needs to evaluate an expression lime
ClockTicks := ...
WaitCnt ( ClockTicks + cnt)
if ClockTicks is smaller than 385 the WaitCnt waits 54 seconds.
If you have more code between calculating ClockTicks and the WaitCnt-Command the minimum is higher.
So did you check if the value of ClockTicks in your code is always high enough?
To avoid resetting you would have to disconnect the RTS or the DSR-line. But when disconnected you could not download new code into the Propeller-Chips RAM nor the EEPROM
downloading code requires a reset.
Some of the calculations you coded are wrong
example your old code was
the new code must come to the same result which is achieved through multiplying 2.45 with 100 to get the same digits without digits behind floating point
2.45 * 100 = 245
So a division by 245 instead of 2.45 leads to a result that is 100time smaller than by dividing with 2.45
so after dividing by 245 there must be a multiply by 100
ClkFreq is usually 80.000.000
So 80.000.000 / 2.45 = 32653061
and the same result if you calculate
80.000.000 / 245 * 100 = 32653061
actually your new code does
80.000.000 / 245 / 10 = 32653
this result is 1000 times smaller than it should be
best regards
Stefan
I will play around with the test programs, as I want to feel confident in using those built in commands correctly.
I did wait 54 seconds and watched on the scope for an output signal. Nothing happened, so I waited a few more minutes, still nothing. I've had that timing issue bite me too many times before not to try that.
The low power waitcnt has always been waitcnt(clkfreq + cnt) so it loops once a second.
I may put switches on those pins if I need to continue troubleshooting this, but since I simplified the program and removed the round object and the float object, it has been working properly today. I want to continue to test it for a few more days before I can say with confidence that it is not hanging anymore, and then hopefully try and identify why it was hanging so that I can learn from this.
The reason I made it 1000 times smaller is because it then simplifies that piece of code and it simplifies the case variables
' (((32653 * 99) = 3232647) * 10) = 32326470 onTime := ((pwmOutputHertzToClkCycles * c_70FahrenheitOn) * 10)The above value is 1000 times bigger than it was because c_70FahrenheitOn would be 99 instead of .99 and then I multiply it by 10 in the end, so it's a wash. This allowed me to cut down on the number of math operations by 2 or 3 and kept me from going over signed int roll over (2^31) so that is why I did it that way. If there is a better way, I'd love to learn it.
I was asking in the forum for code that could be used as "set and forget" pwm-dutycycle.
There was a very quick answer and I tested the code.
I modified it that it works with a frequency of 2.42 Hz
The modifying is somehow quick and dirty but works
The 0-100% dutycycle-version needs a cog but all you have to do
if you want to change the dutycycle-percentage is
a single call of method "PWMctrx3(pwmpin,testfreq,DutyPercentage)"
So all the hassle about how to switch on/off the pwm-pin is over
see democode attached
best regards
Stefan
additional comment:
this is an example how giving an overview leads to a better/easier solution.
If you have a viewing-point on a higher level you can see the "easy to go path" that was hidden behind the "Am I using cogstop correct" bushes
That's the reason why I'm almost everytime asking for an overview = what do you want do do in the end?