Am I using cognew/cogstop correctly?
turbosupra
Posts: 1,088
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
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: Case -1 is evaluating every one of your expressions as true.
Perhaps something along the lines of: Or perhaps even:
Try making test programs to understand behaviors. Here's one that demonstrates the cognew / cogstop, as well as case.
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
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?