![]() |
Forum Index : Microcontroller and PC projects : serial input
Page 1 of 2 ![]() ![]() |
|||||
Author | Message | ||||
georgestheking Newbie ![]() Joined: 21/12/2021 Location: BelgiumPosts: 32 |
Hi, I have problem using INPUT$. I use version picomite 6.00.01 on a RP2350. The serial port work for ouput but input$ always retrun an empy string. LOC(#1) give me a value greater than zero. But INPUT$ always return an empy string. SETPIN GP0, GP1, COM1 OPEN "COM1:115200" AS #1 IF LOC(#1) > 10 THEN data$ = INPUT$(256, #1) Any idea ? Best regards Georges |
||||
phil99![]() Guru ![]() Joined: 11/02/2018 Location: AustraliaPosts: 2535 |
May not work but worth a try. Add a pause to allow processing to complete. IF LOC(#1) > 10 THEN Pause 10 data$ = INPUT$(256, #1) EndIf |
||||
CaptainBoing![]() Guru ![]() Joined: 07/09/2016 Location: United KingdomPosts: 2162 |
maybe I am not up to date on Pico MMBasic, but it looks like you are trying to get 256 charcaters... the maximum in a string is 255. Maybe that is some obscure "gotcha" try something like: b$=Input$(Min(10,Loc(#2)),#2) to grab however many characters are available or just 10, whichever is the lower h Edited 2025-06-09 21:09 by CaptainBoing |
||||
phil99![]() Guru ![]() Joined: 11/02/2018 Location: AustraliaPosts: 2535 |
Well spotted, I completely missed that. |
||||
mozzie Senior Member ![]() Joined: 15/06/2020 Location: AustraliaPosts: 131 |
G'day Georges, The following might explain the situation. OPEN "COM1:115200" as #1 When the serial port is opened, the receive buffer is cleared. IF LOC(#1) > 10 THEN data$ = INPUT$(256, #1) Now we check the buffer, which is empty, so data$ is also empty. So we need to wait for the data to arrive: OPEN "COM1:115200" as #1 Do while LOC(#1)<10 ' loop here until 10 chars in input buffer Loop data$ = INPUT$(255, #1) print data$ You can also use interrupts but hopefully this will help. Regards, Lyle. Edited 2025-06-09 21:33 by mozzie |
||||
georgestheking Newbie ![]() Joined: 21/12/2021 Location: BelgiumPosts: 32 |
Hi, Thanks to everybody but I still have the problem. I forget to say it is a WEBMITE version on the standard PICO 2 W board. Best regards Georges |
||||
CaptainBoing![]() Guru ![]() Joined: 07/09/2016 Location: United KingdomPosts: 2162 |
still with that 256? change it to 255 and report back |
||||
georgestheking Newbie ![]() Joined: 21/12/2021 Location: BelgiumPosts: 32 |
Hi, I already spend many hours with this problem. Here is the complete explanation. The sender send 50 bytes every 10 mS. I use SETTICK to read the serial port every 10 ms. The routine I call : PRINT LOC(#1) give +/- 100 data$=input$(100,#1) give an empty string PRINT LOC(#1) give again +/- 100 ' Then I clear the buffer DO g$=input$(100,#1) LOOP UNTIL LOC(#1)=0 I think it is a timing problem. Things goes too far. We can not read datas during datas is coming. What do you thinks guy ? Best regards Georges |
||||
PhenixRising Guru ![]() Joined: 07/11/2023 Location: United KingdomPosts: 1278 |
I have found the serial communications to be rock-solid (standard PicoMite). I have one arrangement that is multi-drop serial where I continuously poll four PicoMites @921600 BAUD, no delays in the code and it works reliably. |
||||
lizby Guru ![]() Joined: 17/05/2016 Location: United StatesPosts: 3337 |
I'm with Phenix--MMBasic serial is rock solid. If LOC(#1) is greater than 0, you can read bytes. I think there are two things wrong with your loop--you are not adding what you read to g$, and you're looping UNTIL LOC(#1) = 0 instead of DO WHILE LOC(#1) > 0. Try this: g$="" If LOC(#1) > 0 then DO WHILE LOC(#1) > 0 g$=g$+input$(LOC(#1),#1) PAUSE 10 ' allow time for more bytes to arrive if they are coming LOOP endif print g$ (But make sure you don't send more than 255 bytes so you don't overrun g$.) (You can omit the IF ... ENDIF, but it may make it more clear that this block handles serial input when new input has been detected.) ~ Edited 2025-06-10 07:16 by lizby PicoMite, Armmite F4, SensorKits, MMBasic Hardware, Games, etc. on fruitoftheshed |
||||
phil99![]() Guru ![]() Joined: 11/02/2018 Location: AustraliaPosts: 2535 |
A simple test between 2 PicoMites. 'Pico A GP0 pin1 -------> Pico B GP1 pin2 ' Gnd pin3 -------> Gnd pin3 ' Serial Tx test program on Pico A setpin gp1,gp0, com1 : OPEN "COM1:115200" AS #1 dt$=datetime$(now) do do while datetime$(now) = dt$ : loop 'wait for time to change print #1, datetime$(now) 'send it dt$ = datetime$(now) loop ' Serial Rx test program on Pico B SetPin gp1,gp0, com1 : Open "COM1:115200" As #1 g$ = Input$(255,#1) : g$="" 'purge the Rx buffer Do Do While Loc(#1) = 0 : Loop 'wait for data to start arriving Pause 2 'allow time for the rest if the message to arrive 'increase for longer message or lower baud rate Print Loc(#1); " Bytes in Rx buffer", g$ = Input$(255,#1) Print g$; Loop Output > RUN 21 Bytes in Rx buffer 10-06-2025 13:05:37 21 Bytes in Rx buffer 10-06-2025 13:05:38 21 Bytes in Rx buffer 10-06-2025 13:05:39 21 Bytes in Rx buffer 10-06-2025 13:05:40 21 Bytes in Rx buffer 10-06-2025 13:05:41 21 Bytes in Rx buffer 10-06-2025 13:05:42 21 Bytes in Rx buffer 10-06-2025 13:05:43 > Edited 2025-06-10 13:08 by phil99 |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6248 |
One example where I send a command and wait for a reply. Using GP1 and GP0 ' SETPIN GP1,GP0,COM1 OPEN "COM1: 19200" AS #3 ... FUNCTION sendData$(txt$) LOCAL echo$, n PRINT #3, txt$; PAUSE 30 echo$ = INPUT$(200,#3) sendData$ = MID$(echo$,LEN(txt$)+1) 'for n = 1 to len(echo$) 'print hex$(asc(mid$(echo$,n,1)),2); 'next n END FUNCTION I notice that you used Data$ as a variable. I am not comfortable using keywords as variable names but you can get away with it sometimes. Jim VK7JH MMedit |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9553 |
That's pretty fast. I'm not sure that MMBASIC is being given enough time to process things, if it's only allowed 10mS to do any processing, before the next 50 bytes arrive....if you see what I am getting at. Serial is rock-solid, cos I use it all the time in my stuff too, but you have to have enough time for the data to be processed BEFORE expecting the next packet, and 10mS ain't much time at all. Does the sender also send an end-of-packet byte as part of each packet? That way, you can read the data from the buffer, and stop when you detect the EOP byte, process what is required, and then return to the main loop. While that is going on, the serial input buffer will continue to buffer any data received, then you just rinse and repeat forever, or until the buffer is empty. Edited 2025-06-10 16:48 by Grogster Smoke makes things work. When the smoke gets out, it stops! |
||||
PhenixRising Guru ![]() Joined: 07/11/2023 Location: United KingdomPosts: 1278 |
Example of my multi-drop: I always use binary (BIN2STR, STR2BIN) I always have a header &HAA (&b1010 1010) I don't like using PAUSE, prefer to look for single characters and process them immediately. do if loc(2) then b1 = asc(input$(1,2)) if b1=&haa then 'header byte do:loop until loc(2) b1 = asc(input$(1,2)) if b1 = addr then 'is it my address byte? 'You talkin to me? accum="" for i = 1 to 8 'always 8 bytes of data do:loop until loc(2) accum = accum + input$(1,2) next myvalue = str2bin(int64,accum,big) do:loop until loc(2) checksum = asc(input$(1,2)) end if end if end if loop Obviously, this could freeze but that would mean a serious problem and watchdog would happen. @Grogster: I think that, conservatively, 10ms = 1000 lines of execution(?) |
||||
Volhout Guru ![]() Joined: 05/03/2018 Location: NetherlandsPosts: 4975 |
Hi George, The problem is that you read 100 characters at a time. Let's assume at a certain moment there are 105 characters in the UART buffer. You read 100 (leaving 5) so LOC(#1) equals 5. It loops, and you read 100. But there are only 5 in the buffer. So it waits until it gets 100 characters, potentially eating 95 characters of the new message. Volhout P.S. 50 characters every 10ms. What is your plan to do with them. MMBasic is fast (50.000 - 100.000 instructions per second), but that is still a lot of data for interpreted basic. In my morse decoder program I read 32 values every 10ms and do some fft processing, but that has close to 50% CPU power. I am still puzzling how to translate the fft output into characters fast enough. Maybe using lookup tables. Edited 2025-06-11 06:35 by Volhout PicomiteVGA PETSCII ROBOTS |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6248 |
INPUT$() reads upto the given number and will return immediately with whatever there is. It does NOT wait. Looping until LOC() = 0 is OK and a fast way to flush the buffer. Jim VK7JH MMedit |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9553 |
OK then. ![]() I guess I am still thinking in terms of old BASIC interpreters which were very slow compared to MMBASIC. ![]() Smoke makes things work. When the smoke gets out, it stops! |
||||
aFox Senior Member ![]() Joined: 28/02/2023 Location: GermanyPosts: 103 |
Maybe try to increase the receive buffer size within the OPEN command. Gregor |
||||
Volhout Guru ![]() Joined: 05/03/2018 Location: NetherlandsPosts: 4975 |
Thanks Jim, for correcting me. I didn't know it would return immediately. So why the DO LOOP. If you have a 256 buffer, why not use input$(255,#1) Volhout PicomiteVGA PETSCII ROBOTS |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6248 |
So why the DO LOOP. If you have a 256 buffer, why not use input$(255,#1) Volhout With a 256 byte buffer you need two reads. Normally I would have a larger buffer hence the do:loop Once flushed, I use whatever size read is needed for the incoming data with plenty of room to synchronize the stream. VK7JH MMedit |
||||
Page 1 of 2 ![]() ![]() |
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |