ERROR 21...SUBS and FUNCTIONS cannot be nested...(in PROPBASIC)

It does not seem to matter what I do, in the "arrangement of SUB, GOSUB, no SUB at all, I cannot get more then one SUB in a COG. Meaning, I can call a single SUB with the same name, any number of times in a single COG, but if i put another SUB in that same COG, with a different name, I always get the above error message. Yes, I am listing the SUB right after the VARIABLE list like so "getADCdata SUB", but before the DO/LOOP. That SUB does get used 3 times in the DO/LOOP, with three RETURN(s).
Is the problem due to a different SUB, with a different name, being called inside the same above DO/LOOP as the above SUB? "getADCdata SUB"
DennO
Is the problem due to a different SUB, with a different name, being called inside the same above DO/LOOP as the above SUB? "getADCdata SUB"
DennO
Comments
Please post your code. If you can minimize it as much as you can.
P.S. I am confused when you talk about putting SUBs in COGs ?
Do you mean putting SUBs in TASKs ? A "TASK" is not a COG...
A COG is a processor capable of running a TASK.
The main code is a TASK (implied), that is run in COG0 at startup.
A COG can run different TASKs at different times.
Bean
TASK voltMeasure is where I have the only SUB routine running...to get data from the MCP3204...by using 3 different single ended channels for 2 different voltages, and 1 temperature measurement using an LM34.
DennO
DEVICE P8X32A, XTAL1, PLL16X XIN 5_000_000 '========CONSTANTS============ baud CON "N9600" baud2 CON "T115200" carr_return CON 13 clrLCD CON 12 'clear the screen on the lcd posCMD CON 16 'position the curser command hideCUR CON 4 'hide the curser command blinkCUR CON 6 'blink the curser command degreeSYM CON 223 'the "degree" symbol receive_data CON 255 backLTon CON 14 'turn the back light on backLToff CON 15 'turn the back light off brightness_ctl CON 27 quarter_bright CON 48 half_bright CON 49 three_quarter_bright CON 50 full_bright CON 51 beep CON 7 'beep command right_align CON 18 'RIGHT ALIGN COMMAND start_big_char CON 2 end_big_char CON 3 astrike CON 42 block_char CON 134 carReturn CON 13 'carriage return command blank_char CON 32 left_arrow CON 127 right_arrow CON 126 LR_arrow CON 131 LL_arrow CON 128 UR_arrow CON 129 UL_arrow CON 130 down_arrow CON 132 up_arrow CON 133 equal_sign CON 61 first_line CON 64 second_line CON 104 no_char CON 0 trigger CON 50'''''20 Scale CON 205'''''$00CD ''205=CD in HEX inch_conv CON 889 '*conversion factor, uSec TO inches (1/74.746) * 65536 using **. '======== HUB VARIABLES============== longDistance HUB LONG 'location of long distance address longDistance_tenth HUB LONG 'location of long distance tenth/of a foot address compassDegrees HUB LONG 'location of LM34 data volt_location HUB LONG 'location of volt data tenth_location HUB LONG hunds_location HUB LONG temp_location HUB LONG volt_location_12v HUB LONG 'location of volt data tenth_location_12v HUB LONG hunds_location_12v HUB LONG temp_LocationTenths HUB LONG temp_Location_10 HUB LONG temp_Location_100 HUB LONG distanceLocation HUB LONG MCPValueLocation HUB LONG '============= VARIABLES ======================= '========[PIN ASSIGNMENTS]======== 'Assignments of pin go in each COG that is using that pin.. '========[TASK ASSIGNMENTS]=============== LCD_1 TASK longDistSensor TASK compass TASK volt_measure TASK LED_blink TASK blinkAnotherLED TASK sonicDistance TASK PROGRAM Start 'this is running in COG 0 Start: '========PIN ASSIGNMENTS======== LED_blue PIN 16 '=============================== COGINIT sonicDistance, 1 'cog 1 COGINIT blinkAnotherLED, 2 'cog 2 COGINIT LED_blink, 3 'cog 3 COGINIT volt_measure, 4 'cog 4 COGINIT longDistSensor, 5 'cog 5 COGINIT compass , 6 'cog 6 COGINIT LCD_1, 7 'cog 7 DO PAUSE 500 TOGGLE LED_blue PAUSE 500 LOOP END '=============================================== TASK sonicDistance 'RUNNING IN COG 1 '========[PIN ASSIGNMENTS]===================== PingPin PIN 14 LOW ' Connected to Sig pin on Ping module '========[VARIABLES]=========================== inDistance VAR LONG valueStr3 HUB string(4) DO PAUSE 100 PULSOUT PingPin, 5 ' Trigger PING PAUSEUS 5 PULSIN PingPin, 1, inDistance ' Measure PING pulse inDistance = inDistance / 2 'divide by 2 for one way inDistance = inDistance * 100 'multiply by 100 for interger math inDistance = inDistance / 7374 'divide by 73.74 uSec/1 inch...7374 WRLONG distanceLocation, inDistance ' valueSTR3 = STR inDistance,4,5 ' SEROUT 30, baud2, valueSTR3 ' SEROUT 30, baud2, 10 LOOP ENDTASK sonicDistance '============================================ TASK longDistSensor 'this TASK is running in COG 5...a simple math problem '========[PIN ASSIGNMENTS]===================== triggerPin PIN 10 OUTPUT sensorPin PIN 11 INPUT '========[VARIABLES]=========================== target VAR LONG target_dist VAR LONG target_tenth VAR LONG valueTargetDist HUB string(7) 'valueTargetDistTenth HUB string(1) DO sensorPin = 0 PULSOUT triggerPin, Trigger '* activate sensor by pulsing HIGH PAUSEUS 5 RCTIME sensorPin, 1, target_dist '* measure echo pulse.. target_dist = target_dist / 2 target_dist = target_dist * 100 'multiply by 100 for interger math target_dist = target_dist / 7374 'divide by 73.74 uSec/1 inch...7374...inches to target WRLONG longDistance, target_dist PAUSE 50 LOOP ENDTASK longDistSensor '================================================================ TASK compass 'this TASK is running in COG 6 '========[PIN ASSIGNMENTS]========== CMPS10_PWM PIN 24 '========[VARIABLES]=========================== rawHeading1 VAR LONG rawHeading2 VAR LONG rawHeading3 VAR LONG rawHeadingAve VAR LONG valueSTR4 HUB string(4) valueSTR HUB string(4) DO PULSIN CMPS10_PWM, 1, rawHeading1 rawHeading1 = rawHeading1 - 1200 rawHeading1 = rawHeading1 / 100 ''whole degree rawHeading1 = ABS rawHeading1 PAUSE 50 PULSIN CMPS10_PWM, 1, rawHeading2 rawHeading2 = rawHeading2 - 1200 rawHeading2 = rawHeading2 / 100 ''whole degree rawHeading2 = ABS rawHeading2 PAUSE 50 PULSIN CMPS10_PWM, 1, rawHeading3 rawHeading3 = rawHeading3 - 1200 rawHeading3 = rawHeading3 / 100 ''whole degree rawHeading3 = ABS rawHeading3 PAUSE 50 rawHeadingAve = rawHeading1 + rawHeading2 rawHeadingAve = rawHeadingAve + rawHeading3 rawHeadingAve = rawHeadingAve / 3 PAUSE 50 WRLONG compassDegrees, rawHeadingAve valueSTR = STR rawHeadingAve,4, 5 ' SEROUT 30, baud2, 10 ' SEROUT 30, baud2, valueSTR PAUSE 50 LOOP ENDTASK compass '================================================== TASK LCD_1 LMM 'this TASK is running in COG 7 '========[PIN ASSIGNMENTS]======== LCD_data_out PIN 2 '========[VARIABLES]=========================== VOLT VAR LONG VOLTtenth VAR LONG VOLThunds VAR LONG VOLT_12v VAR LONG VOLTtenth_12v VAR LONG VOLThunds_12v VAR LONG MCPValue VAR LONG TEMP_100 VAR LONG TEMP_10 VAR LONG TEMP_tenths VAR LONG valueSTRtenth HUB string(4) inDistance VAR LONG rawHeadingAve VAR LONG target_dist VAR LONG target_tenth VAR LONG '======================================================================= 'the following DATA statments are to preload the display, the variables are loaded elsewhere in the program. LCD_data_0 DATA clrLCD,beep,backLTon PAUSE 100 LCD_data_1 DATA posCMD,64,"LDis=",posCMD,74,"TEMP=",0 'LCD...line 1 LCD_data_2 DATA posCMD,84,"COMPASS=",posCMD,95,degreeSYM,posCMD,100,"IN'S",0 'LCD...line 2 LCD_data_3 DATA posCMD,104,"VOLTAGE=",posCMD,115,".",posCMD,119,"volts",0 LCD_data_4 DATA posCMD,124,"VOLTAGE=",posCMD,135,".",posCMD,139,"volts",0 SEROUT LCD_data_out, baud, LCD_data_0 'clear the screen, beeb, and turn on the back light SEROUT LCD_data_out, baud, LCD_data_1 'to print line 1 SEROUT LCD_data_out, baud, LCD_data_2 'to print line 2 SEROUT LCD_data_out, baud, LCD_data_3 'to print line 3 SEROUT LCD_data_out, baud, LCD_data_4 'to print line 4 DO ' A LONG DIATANCE MEASUREMENT RDLONG longDistance, target_dist 'reading the temperature data that is in the HUB PAUSE 50 RDLONG longDistance_tenth, target_tenth PAUSE 50 LCD_data_1a DATA posCMD,69," ",0 LCD_data_1a(2) = STR target_dist,3,5 SEROUT LCD_data_out, baud, LCD_data_1a ' A COMPASSS ANGLE MEASUREMENT and DISTANCE MEASUREMENT RDLONG compassDegrees, rawHeadingAve PAUSE 50 'reading the temperature data that is in the HUB RDLONG distanceLocation, inDistance PAUSE 50 LCD_data_2a DATA posCMD,92," ",posCMD,96," ",0 LCD_data_2a(2) = STR rawHeadingAve,3,5 LCD_data_2a(7) = STR inDistance,3,5 SEROUT LCD_data_out, baud, LCD_data_2a ' THIS IS A READING FROM A VARAIBLE 5 VOLT RDLONG volt_location, VOLT 'reading the voltage data that is in the HUB PAUSE 50'100 RDLONG tenth_location, VOLTtenth 'reading the voltage data that is in the HUB PAUSE 50'100 RDLONG hunds_location, VOLThunds 'reading the voltage data that is in the HUB PAUSE 50'100 ' THIS IS A READING FROM A LM34 RDLONG temp_location_100, TEMP_100 PAUSE 50'100 RDLONG temp_locationTenths, TEMP_tenths PAUSE 50'100 LCD_data_1aa DATA posCMD,79," ",posCMD,81,".",posCMD,82," ",posCMD,83,degreeSYM,0 LCD_data_1aa(2) = STR TEMP_100,2,5 LCD_data_1aa(9) = STR TEMP_tenths,1,5 SEROUT LCD_data_out, baud, LCD_data_1aa LCD_data_3a DATA posCMD,114," ",posCMD,116," ",posCMD,117," ",0 LCD_data_3a(2) = STR VOLT,1,5 LCD_data_3a(5) = STR VOLTtenth,1,5 LCD_data_3a(8) = STR VOLThunds,1,5 SEROUT LCD_data_out, baud, LCD_data_3a ' THIS IS A VOLTAGE MEASUREMENT OF INCOMING SUPPLY VOLTAGE RDLONG volt_location_12v, VOLT_12v PAUSE 50'100 RDLONG tenth_location_12v, VOLTtenth_12v PAUSE 50'100 RDLONG hunds_location_12v, VOLThunds_12v PAUSE 50'100 RDLONG MCPValueLocation, MCPValue PAUSE 50 IF MCPValue < 9426 THEN '9828/819 = 12.00 volts...beep warning SEROUT LCD_data_out, baud, beep PAUSE 100 ENDIF LCD_data_4a DATA posCMD,133," ",posCMD,136," ",posCMD,137," ",0 LCD_data_4a(2) = STR VOLT_12v,2,5 LCD_data_4a(6) = STR VOLTtenth_12v,1,5 LCD_data_4a(9) = STR VOLThunds_12v,1,5 SEROUT LCD_data_out, baud, LCD_data_4a LOOP ENDTASK LCD_1 '================================================================ TASK volt_measure 'this TASK is running in COG 4 '========[PIN ASSIGNMENTS]========== ADC_Clk PIN 21 LOW ' MCP3204.11 ADC_Dout PIN 20 LOW ' MCP3204.10 ADC_Din PIN 19 LOW ' MCP3204.9 ADC_CS PIN 18 HIGH ' MCP3204.8 '========[VARIABLES]=========================== 'valueSTR HUB string (4)'''VAR LONG MCPValue VAR LONG VOLT VAR LONG VOLTtenthx10 VAR LONG VOLTtenth VAR LONG VOLThunds VAR LONG VOLT_12v VAR LONG VOLTtenth_12v VAR LONG VOLTtenth_12vx10 VAR LONG VOLThunds_12v VAR LONG voltChannel VAR LONG TEMP_100 VAR LONG TEMPtenths VAR LONG TEMPtenthsx10 VAR LONG TEMP_100x100 VAR LONG TEMPremainder VAR LONG getADCdata SUB DO voltChannel = %11000'voltChannel is used to select the proper channel for the MCP3204 ADC in the SUB ROUTINE..CH0 GOSUB getADCdata 'this MCPValue is for the variable voltage...0 to 5 volts VOLT = MCPValue / 819 '=4 actual 4 volts VOLTtenth = MCPValue//819 VOLTtenthx10 = VOLTtenth * 10 VOLTtenth = VOLTtenthx10 / 819 VOLThunds = VOLTtenthx10 // 819 VOLThunds = VOLThunds * 10 VOLThunds = VOLThunds / 819 WRLONG volt_location, VOLT PAUSE 50 WRLONG tenth_location, VOLTtenth PAUSE 50 WRLONG hunds_location, VOLThunds PAUSE 50 voltChannel = %11001 ''CH1 tomeasure input voltage 12 VOLT measure GOSUB getADCdata MCPValue = MCPValue * 3 'voltage divider...3 10K resistors in series. WRLONG MCPValueLocation, MCPValue VOLT_12v = MCPValue/819 VOLTtenth_12v = MCPValue//819 VOLTtenth_12vx10 = VOLTtenth_12v * 10 VOLTtenth_12v = VOLTtenth_12vx10 / 819 VOLThunds_12v = VOLTtenth_12vx10 // 819 VOLThunds_12v = VOLThunds_12v * 10 VOLThunds_12v = VOLThunds_12v / 819 WRLONG volt_location_12v, VOLT_12v PAUSE 50 WRLONG tenth_location_12v, VOLTtenth_12v PAUSE 50 WRLONG hunds_location_12v, VOLThunds_12v PAUSE 50 voltChannel = %11010 ''CH2 to measure the actual temperature with an LM34 sensor GOSUB getADCdata TEMP_100 = MCPValue * 100 TEMP_100x100 = TEMP_100 TEMP_100 = TEMP_100x100 / 819'whole degrees..units and tens TEMPremainder = TEMP_100x100 // 819 TEMPtenths = TEMPremainder * 10 TEMPtenths = TEMPtenths / 819 WRLONG temp_location_100, TEMP_100 PAUSE 50 WRLONG temp_locationTenths, TEMPtenths PAUSE 50 LOOP SUB getADCdata LOW ADC_CS ' Enable MCP3204 PAUSE 100'''''''''PAUSEUS 100 SHIFTOUT ADC_Din, ADC_Clk, MSBFIRST, voltChannel\5 ' Select CH0, Single-Ended SHIFTIN ADC_Dout, ADC_Clk, MSBPOST, MCPValue\13 ' Read ADC HIGH ADC_CS ' Disable ADC LOW ADC_Clk RETURN ENDTASK volt_measure '==================================================== TASK LED_blink 'this task is running in cog 3 LED_white PIN 17 DO PAUSE 100 TOGGLE LED_white PAUSE 100 LOOP ENDTASK LED_blink '======================================================== TASK blinkAnotherLED 'RUNNING IN COG 2 LED_blue_2 PIN 15 DO PAUSE 50 TOGGLE LED_blue_2 PAUSE 50 LOOP ENDTASK blinkAnotherLED '======================================================
The only thing I see wrong is you do NOT put the task name after ENDTASK. But I don't think that causes an error, but it might confuse the compiler.
Bean
Ah, good catch. I didn't see that...
Bean
If you have more than one SUB without the ENDSUB, I suspect the compiler interprets that as defining a subroutine within a subroutine.
Bob
RETURN Return from a subroutine or function. RETURN value{,value{,value{,value}}}
Bean, the code in the above thread does compile and run with no errors. The problem I was having was using another SUB routine in the same task and then getting ERROR 21. I will try as jones suggested. Also, Bean, I believe I do have the task name after each (7 of them) ENDTASK(s). I double checked....anyways...thanks again...DennO
Addendum: jones...I just installed a practice SUB in the same TASK as the first SUB and declared it, and the program compiled. So, that was my problem...I was using RETURN, as in PBASIC with the Stamp...thanks again to all....
So ENDSUB tells the compiler that is the end of the SUBROUTINE.
For example you might do:
SUB Test DO RDLONG hubVar, A IF A = 1 THEN RETURN ENDIF LOOP ENDSUB
Bean
Wasn't GOSUB obsoleted ? I seem to remember this was stated in the doc's.
On another note, does anyone know why my Windows 7, will not stop downloading the same ZIP file. It goes crazy, and i have to back out of Chrome, or reboot by holding the off button down for 5 seconds. Then I have to open my download files, and delete 20 of the same ZIP file. It will not stop after one... Just thought I would ask, as some of the PROPBASIC examples are in ZIP format...
DennO...also the dog's name is Lincoln...
I'd have to check the source code to be sure...
Bean
It's Microsoft Windows. Who knows why it does anything? I switched to Linux Mint a while ago and have not regretted it in spite of having to hunt for Linux versions of several apps. IMPNSHO it's past time to abandon Windows and switch to open source software.
Bean, is there anyway to preform integer math with PROPBASIC, with more then one operator on one line...please see attached code to obtain tens, units, tenths, and hundreds of a volt...
voltChannel = %11001 ''CH1 tomeasure input voltage 12 VOLT measure GOSUB getADCdata MCPValue = MCPValue * 3 'voltage divider...3 10K resistors in series to keep voltage below 5 volts max for the MCP3204 or MCP3208. WRLONG MCPValueLocation, MCPValue VOLT_12v = MCPValue/819 VOLTtenth_12v = MCPValue//819 VOLTtenth_12vx10 = VOLTtenth_12v * 10 VOLTtenth_12v = VOLTtenth_12vx10 / 819 VOLThunds_12v = VOLTtenth_12vx10 // 819 VOLThunds_12v = VOLThunds_12v * 10 VOLThunds_12v = VOLThunds_12v / 819 WRLONG volt_location_12v, VOLT_12v PAUSE 50 WRLONG tenth_location_12v, VOLTtenth_12v PAUSE 50 WRLONG hunds_location_12v, VOLThunds_12v PAUSE 50
Thanks..DennO
So just do this:
' Convert 819 per volt to 100 per volt MCPvalue = MCPvalue */ 8003 ' same as *100 /819 volts10 = MCPvalue / 1000 volts = __remainder / 100 tenths = __remainder / 10 hunds = __remainder
Bean
I will rewrite my code and remember your instructions..and I did, so, 4 lines of code (your help) replaced 7 lines, to do the same thing. Very good....what can I say....other then I am looking for 1.49...LOL
DennO
' Convert 819 per volt to 100 per volt MCPvalue = MCPvalue */ 8003 ' same as *100 /819 volts10 = MCPvalue / 1000 volts = __remainder / 100 tenths = __remainder / 10 hunds = __remainder
which does work, and save alot of code space, which I mentioned in my previous post.Now, I am using an LM34 temperature sensor, operating on 5 volts supply. I am using the following code to get the temperature reading on the LCD to whole degrees and tenth of a degree. Which does work. Later on, I send it to the LCD using DATA statments.
GOSUB getADCdata TEMP_100 = MCPValue * 100 TEMP_100x100 = TEMP_100 TEMP_100 = TEMP_100x100 / 819'whole degrees..units and tens TEMPremainder = TEMP_100x100 // 819 TEMPtenths = TEMPremainder * 10 TEMPtenths = TEMPtenths / 819
However in trying to get "your"version to work, I cannot seem to duplicate it. I have tried several different ways, with no luck. You converted the 819 ADC units to 100 ADC units per volt. Which gave me the */8003 to use with the MCPvalue. In trying to do the same with 5 volts, I am not having much success. (Need a call to the expert)...the resolution of the MCP3204 is 12 bit for 5 volts. This give us the 891/volt. Would appreciate your thoughts....
The LM34 outputs 10mvolt/degreeF...I did try to convert to 5 volts by dividing 5 by 819, which gives me a value of .0061. That value * 65536 gives 388 to use with the */MCPvalue. Still no joy...what am I missing? Hope I am making sense to you or the other readers...
Again thanks....DennO
Temperature calculation with a 12 bit adc and 5V reference would be ADCreading x 500 / 4095.
GOSUB getADCdata 'this SUB gust gets the ADCunits, or as I call them MCPvalue.. MCPvalue = MCPvalue */ 80019''''''3 ' same as *1000mv /819 = 1.22 * 65536 using the */ binary operator = 80019 TEMP_100 = MCPvalue / 10''''''''0 TEMPtenths = __remainder * 10 TEMPtenths = TEMPtenths / 10
I owe this trick to Bean...
DennO
DennO