Replacing manual RxCheck signal with a self generated signal
Elkin
Posts: 58
Below is my code where currently I have to press the spacebar on my terminal window to quit the logfile loop and start a new one. I would like to write something simple that can start a new signal with a self generated signal. Any ideas?
PUB Main Repeat '5 runs/hour, 120 runs/day, 840 runs/wk OUTA [P0] := 0 Syringe.Signal waitcnt(time += 400_000_000) '5 sec Valve.Switch repeat 24 waitcnt(time += 800_000_000) '240 sec Syringe.Signal repeat 35 waitcnt(time += 800_000_000) '350 sec outa [P11] := 0 waitcnt(time += 800_000_000) '10 sec Valve.Switch [COLOR=#ff0000] ***SIGNAL NEEDED HERE*** 'Quit data gathering for this file[/COLOR] waitcnt(time += 400_000_000) '5 sec OUTA [P11] := 1 OUTA [P2] := 1 OUTA [P0] := 1 Syringe.Signal PUB SD_main | check, sync, count, ch0, c, len, FileNumber ADC.init (CS, CLK, DIO) pause(1) 'term.tx(CLS) term.str(string("-- SD Card Datalogger", CR, CR)) term.rxflush 'check := term.rx check := \sdcard.mount_explicit(SD_DO, SD_CLK, SD_DI, SD_CS) if (check == 0) term.str(string("-- sd card mounted", CR)) else term.str(string("-- ERROR: sd card failed to mount", CR)) repeat waitcnt(0) ' stop here repeat FileNumber from 1 to 9999 'maximum number of files allowed (9999) ZeroPad(FileNumber, 4, @logfile + 4) term.str(@logfile) term.tx(13) check := \sdcard.popen(@logfile, "w") ' attempt to create if (check == 0) term.str(string("-- log file created; logging started", CR)) \sdcard.pputs(@header) ' column header in CSV else term.str(string("-- ERROR: could not create log file", CR)) repeat waitcnt(0) term.rxflush sync := cnt count := 1 repeat read_adc(@ch0) ' get data ' write to log file \sdcard.pputs(dec2str(count, @sbuf)) ' write count \sdcard.pputc(",") ' separate \sdcard.pputs(dec2str(ch0, @sbuf)) ' write ch0 value \sdcard.pputs(@crlf) ' terminate line [COLOR=#ff0000] if (term.rxcheck <> -1) ' if key pressed[/COLOR] quit ' abort waitcnt(sync += clkfreq/20) ' update every 50 milliseconds (20 Hertz) count += 1 ' update readings count
Comments
If you are trying to signal between one COG and another, the simplest is either with a shared variable, or using the LOCKxxx commands. These are hardware mutexes that you can use to synchronize operations between multiple cogs.
I'm sure there's a way to do what you want. What criteria do you want to use to indicate it's time to start a new log?
Even if the loops don't always take a set amount of time there are other ways to accurately time a log file.
Frank
If the later, could you use:
I was looking for accuracy in timing, and the ability to capture multiple inputs simultaneously with no time skew between a set of samples. To do this I created a timebase generator in a separate cog. The timebase currently is free running, however due to a code example from one of the the pasm for beginners posted by JAZZED (#345), it could easily be made to stop and run under control of a external command word passed from the master control cog.
The signals generated are single pin outputs for clk, CSEL, acq. The first two signals are specifically to drive the MCP3201 A/D converter, while the acq tells the acquisition module when to sample the A/D bit. So, no subrs in the way, no returns to worry about, no shared memory issues to add jitter to the timing, just a rock stable clock system based on the cogs counters and some waitxxx to syncronize the stuff with plenty of headroom for a faster A/D device.
What this clock generator then allows for it to have multiple identical A/Ds tied to their own cog all capturing syncronously. As many cogs as you want to capture from from 1-5 on a single chip, or assuming special handling, processing and logging, maybe fewer on a single chip, but yet expandable by linking the control lines to as many prop chips as you want to gang together. And again the magic in this method is that the only values that were passed to the cogs were the pin and cog assignments. For timing and control, this made the most sense for the project in question.
So for fast accurate repeatable timing sequences, I used the counters and monitored the outputs and pin assignments to control peripherals. Not the only way to do it, just the way I chose for this application.
Frank Freedman, CRES
P.s. Is this device going to be an infusion / syringe pump of a sort?
Is timing periodic or dynamic? Is timing dependent on other factors?
The only thing that I want the Read ADC repeat loop to be dependent on is the repeat loop in the main driver. The signal can be whatever it needs to be as long as it meets this requirement. The file system should look like this at the end:
ADC_0001.txt
(after about 12 minutes)
ADC_0002.txt
(after about 12 minutes)
...
ADC_2499.txt
(after about 12 minutes)
ADC_2500.txt
I want the freedom to be able to go into the main driver loop and change the timing of that loop so that instead of 12 minutes it could be 10 or 15 minutes between the start of a new logfile (ADC_xxxx.txt).
I do think that franks idea could work but I feel like there has got to be a more simple solution to this. If rxcheck <> -1 does this exactly like I want, isnt there something that I can replace this with that would quit the current logfile and open a new one? The only thing that I want to do is have a specifically defined point in the mainDriver loop that can tell the read_adc loop to quit sampling, close the current logfile, and open a new logfile.
This issue has frustrated me for a while but I feel like this is something that is too simple and I am just overlooking it. What does rxcheck actually send (from FullDuplexSerial)? is it possible to just have a free I/O send that same signal to the Rx pin? I know that isnt really the right way to do this but that seems like it would be a simple way to fix this issue.
Frank, I am running several different types of pumps. The syringe pump program is loaded into the pump and signaled by the propeller with a quick pulse (10th of a second I think) which starts the current pumping program (withdraw or infuse).
Anyway, the write method in the code below increments the "command" byte every 100ms. The Read method samples the command byte every 10ms. Read is looking for the value 0x10. Read triggers a message on the second 0x10 found.
I usually use memory locks when two processes access the same resource.
I also have a PASM 4 x timer that is accurate to 1/512 of a second and up to 24 days. An associated pin transitions from high to low when the timer reaches zero. You are welcome to the code.. I have to find it.
The requirement is that when the sequence in the mainDriver repeat loop reaches a certain point (where I have labeled in red, SIGNAL HERE) the mainDriver directs the read_adc loop in SD_main to quit the loop. When this loop quits, it goes into a bigger loop which will increment the logfile number and open another file with ADC_xxxx.txt where the xxxx is one number greater than the last logfile (this is also labeled in red further down in the code). While the program is running it takes the program about 12 minutes to get get through this main loop each time, hence the 12 minutes. I need to be able to vary that time by changing the waitcnt periods so that is why I need a timed signal from the mainDriver loop to tell the read_adc loop to quit.
I think what you have posted here will work for me as long as I can get it written in my program correctly. I dont know if the fact that my mainDriver loop and AD_main loop are operating on different cogs will have an effect on this but it doesnt seem like it will since you have your read and write that way here. as long as the stopping of the SD_main loop is dependent on the mainDriver loop a tenth of a second shouldnt be a problem. What I mean by that is at most it is only going to be delayed by 0.1 seconds and that will not be compounded in every run (which was what I was worried about).
The fact that the program you have written is something that is constantly sampling makes me fell a little bit better about this. That is essentially what the rxcheck was doing here before. If a key was pressed then it was not equal to -1 which meant it would quit the loop. This seem like the same thing. I am going to give it a shot and wee what I can figure out.
Thanks for the help!
Elkin, Absolutely this is possible.
What signal do you want to use to do this? You said somethink about a valve switching twice. Is the Prop controlling this switch or can the Prop monitor the switch. You can certainly have the logfile stop after a set number of switches or a specific time after the second switch. This is what the Prop is for. It's just a small matter of programming.
Could you post your whole code as an archive? Let me know what signal to use (after how many counts) and what kind of delay, if any, after the signal. This shouldn't be causing you so much grief when you have so many willing to help.
If it is possible to completely do away with the Syringe.EndRun pub block (line 238) and replace this with a simple signal that mimics (rxcheck <>-1) then I could use one of the free pins that i have (pin 3 for example) and just do this directly. Rather than me pushing a key, the prop would generate the rxcheck signal at the given time (line 191) and line 303 could stay the same as (IF(term.rxcheck <> -1)). I could just make a small jumper wire from pin 3 to the rx pin and my problem would be solved.
There really is no counting or delays if pin 3 can be made to send that signal at line 191 of the code.
I would of course like to make this signal something different so that I dont accidentally try to type something and make 5 new files but that isnt nearly as important as getting this to work correctly.
Thanks for all the help!
SyringePump.spin
Around line 191 in Version 3.2.spin
There is some added complexity because SyringePump.spin is started twice. The DAT section (isEndRun I added) is created once. A VAR would be created twice, one for each instance of SyringePump. You probably need to create memory locks else there might be unexpected results. However, it's not clear why you have two instance of SyringePump invoking methods in the same code blocks. Essentially both instance of SyringePump are equal, since there are no unique members.