Es gibt bei VB2005 eine Eigenart mit Strings umzugehen die mich einige Suche gekostet hat.
Wenn ich die Zeilen richtig verstehe:

Do Until Me.SerialPort1.ReadChar()="S?"
Loop

ist „S?“ wegen der Ausrufungszeichen ein String. und den vergleichst du mit dem Empfangsergebnis.
Ich hoffe mal das ReadChar() auch mehr als einen Char liefert weil die Sache sonst sowieso nie passt.
Jetzt zu der Eigenart:
Das kann man am besten im Debug Modus sehen.
Setze einen Breakpoint auf die Zeile.
lass das Programm anlaufen.
wenn es am Breakpoint hält schau dir den Inhalt von ReadChar an.
Achte darauf ob bei dem angezeigten String vorne UND hinten das Ausführunszeichen ist.
wenn es hinten nicht ist musst du ein unsichtbares Zeichen mit einem kleinen Befehl abschneiden und dann funktioniert der Stringvergleich auch wieder .
Falls das so ist kann ich Dir die Lösung Posten.

Netter Gruß