FreeBasic communication with Arduino logic error?

For issues with communication ports, protocols, etc.
Dr_D
Posts: 2451
Joined: May 27, 2005 4:59
Contact:

Re: FreeBasic communication with Arduino logic error?

Post by Dr_D »

Thanks for the image hosting site... I have no idea why imgur didn't work. .. probably something to do with money. lol
Anyway, I will post what I have, but I'm not out of ideas just yet.
I'm still learning... maybe I missed something simple.
If I can, I'd like to find it myself.
If not, I'll ask again... but hopefully, my next post will be have full working code, on both ends, and a simple diagram of the circuit. :)
dasyar
Posts: 372
Joined: Dec 04, 2008 15:31

Re: FreeBasic communication with Arduino logic error?

Post by dasyar »

WOW! This turning out to be one great tutorial on serial programming.

I have been using PySerial for all of my serial comm programs, but I think that I will start at the beginning of this thread, and start giving the code examples a better look. Now , if you were to squeeze in some examples of how to implement some threading, that works in a meaningful way, that would cover a lot of serial comm programming.

Thanks for the great effort that is put into this.
Dr_D
Posts: 2451
Joined: May 27, 2005 4:59
Contact:

Re: FreeBasic communication with Arduino logic error?

Post by Dr_D »

Ok... I know how crazy this image looks, but I'm not sure of another way to do it just yet. lol
Anyway, I removed any communication back from the Arduino, and the lag has pretty much gone away. The code for both sides is below, but the Arduino code hasn't changed much at all... basically just removed any data sent from that side.

Image

FreeBasic code...

Code: Select all

#include "fbgfx.bi"

screenres 640,480,32,,FB.GFX_HIGH_PRIORITY


dim shared DEVICE_COM as string
dim as boolean conOk = false
dim as integer ARD = freefile


for i as integer = 1 to 10

	DEVICE_COM = "COM" & str(i)

	DEVICE_COM = "COM3"

	if( open com(DEVICE_COM & ":9600,n,8,1,cs0,ds0,cd0,rs" for binary As #ARD) <> 0 ) then
		print "error connecting to Arduino on " + DEVICE_COM
	else
		conOK = true
		exit for
	end if

next


if conOK then

	print "Arduino connected on " + DEVICE_COM
	sleep 1000,1
else

	print "Failed to connect to Arduino"
	sleep 5000, 1
	end 1

end if


dim as string oTime, aTime, sHour, sMinute, sSecond, sTimeCode, temp


do


	oTime = aTime
	aTime   = time
	sTimeCode = ""

	temp   = bin(val(mid(aTime,1,2)), 6)
	sHour = ""
	for i as integer = len(temp) to 1 step -1
		sHour+=mid(temp,i,1)
	next

	temp = bin(val(mid(aTime,4,2)), 6)
	sMinute = ""
	for i as integer = len(temp) to 1 step -1
		sMinute+=mid(temp,i,1)
	next

	temp = bin(val(mid(aTime,7,2)), 6)
	sSecond = ""
	for i as integer = len(temp) to 1 step -1
		sSecond+=mid(temp,i,1)
	next

	temp = sHour+sMinute+sSecond

	for i as integer = len(temp) to 1 step -1
		sTimeCode+=mid(temp,i,1)
	next

	sTimeCode+=chr(13)

	screenlock

	if oTime<>aTime then
		cls
		print sTimeCode
		put #ARD,,sTimeCode
	end if

	screensync
	screenunlock

	sleep 3, 1

loop until multikey(FB.SC_ESCAPE)

Arduino code...

Code: Select all

/*
   Time Code Message Format:
   hhhhhhmmmmmmssssss<CR>

   hhhhhh = hours in binary text format ('0' or '1' characters only)
   mmmmmm = minutes in binary text format ('0' or '1' characters only)
   ssssss = seconds in binary text format ('0' or '1' characters only)
   <CR>   = end of message character chr(13)

   19 bytes total
*/

const int SER = 12;   // (595 pin 14)serial input line goes to the *first* shift register... daisy chain, so each QH(PIN 9) goes to the next SER, etc, etc...
const int SRCLK = 11; // (595 pin 11)the serial clock line, or the sync pulse, normal state is low... write, high, back to low, etc...
const int SRCLR = 10; // (595 pin 10)clear memory line, normal state is high... drop to low then back to high to clear memory...
const int RCLK = 9;   // (595 pin 12)copy register line, normal state is low... send high then back to low to copy states...
const int OE = 8;     // (595 pin 13)enable output line... send low to enable, high to disable...

const int TOTAL_SHIFT_PINS = 18;

void setup() 
{
  pinMode(SER, OUTPUT);
  pinMode(SRCLK, OUTPUT);
  pinMode(SRCLR, OUTPUT);
  pinMode(RCLK, OUTPUT);
  pinMode(OE, OUTPUT);

  Serial.begin( 9600 );
  while ( !Serial )
    delay(1);

  //Serial.print( "Arduino is online - demo 5\n" );
  //Serial.flush();

  SR_clearRegisters();
  SR_copyToStorage();
  SR_turnOutputsOn();
}

void loop()
{
  // preserve inTimeCode[] and inCount between calls,
  // we may not receive the entire message in one loop through
  static uint8_t inTimeCode[19];
  static int inCount = 0;
  int16_t ch = -1;

  // read one char at a time (basically guarantees we never
  // see the whole message in one call to loop()
  ch = Serial.read();

  // valid char? add it to inTimeCode[]
  if ( ch != -1 )
  {
    inTimeCode[inCount] = ch;
    inCount += 1;
  }

  // buffer full, but no CR? it's bad, start over
  if ( (ch != 13) && (inCount == 19) )
  {
    inCount == 0;
    //Serial.write( "bad time code, too long/n" );
    //Serial.write( 13 );
  }

  // got a CR, but buffer not full yet? it's bad, start over
  if ( (ch == 13) && (inCount != 19) )
  {
    inCount == 0;
    //Serial.write( "bad time code, too short/n" );
    //Serial.write( 13 );
  }

  // got a CR and buffer full? maybe it's OK... let's check
  if ( (ch == 13) && (inCount == 19) )
  {
    for ( int i = 0; i < 18; ++i )
    {
      if ( (inTimeCode[i] != '0') && (inTimeCode[i] != '1') )
      {
        // bad data, start over
        inCount == 0;
        //Serial.write( "bad time code, invalid data/n" );
        //Serial.write( 13 );
        break;
      }
    }
    // we already know last char is CR, so no need to check that
  }

  // still have a full buffer?  it has to
  // be good... we threw all the bad data away
  if ( inCount == 19 )
  {
    SR_turnOutputsOff();
    for ( int l = 0; l < 18; ++l )
    {
      if (inTimeCode[l] == 49 )
      {
        SR_shiftDataIn(HIGH);
      }
      else
      {
        SR_shiftDataIn(LOW);
      }

      //Serial.write( inTimeCode[l]);
      //Serial.write( 32 );
    }
    SR_copyToStorage();
    SR_turnOutputsOn();
    //Serial.write( 13 );
    //Serial.flush();
    // done with the valid time code, start over, so we can get the next one
    inCount = 0;
  }
}


void SR_turnOutputsOn()
{
  digitalWrite(OE, LOW);
}

void SR_turnOutputsOff()
{
  digitalWrite(OE, HIGH);
}

void SR_clearRegisters()
{
  digitalWrite(SRCLR, LOW);
  digitalWrite(SRCLR, HIGH);
}

void SR_shiftDataIn(int data)
{
  digitalWrite(SER, data);
  digitalWrite(SRCLK, HIGH);
  digitalWrite(SRCLK, LOW);
}

void SR_copyToStorage()
{
  digitalWrite(RCLK, HIGH);
  digitalWrite(RCLK, LOW);
}
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: FreeBasic communication with Arduino logic error?

Post by MrSwiss »

Dr_D wrote:Anyway, I removed any communication back from the Arduino, and the lag has pretty much gone away.
Have you tried with higher baudrate settings? (I never go below 19200, minimum)
I've run my *very old Arduino* (pre Ono model) at speeds up to (and including) 115200 baud.
The real HW communication is after all USB, the COM port is just virtual (VCP).
Dr_D
Posts: 2451
Joined: May 27, 2005 4:59
Contact:

Re: FreeBasic communication with Arduino logic error?

Post by Dr_D »

MrSwiss wrote:
Dr_D wrote:Anyway, I removed any communication back from the Arduino, and the lag has pretty much gone away.
Have you tried with higher baudrate settings? (I never go below 19200, minimum)
I've run my *very old Arduino* (pre Ono model) at speeds up to (and including) 115200 baud.
The real HW communication is after all USB, the COM port is just virtual (VCP).
I haven't, but I will. Great idea. :)
h4tt3n
Posts: 698
Joined: Oct 22, 2005 21:12
Location: Denmark

Re: FreeBasic communication with Arduino logic error?

Post by h4tt3n »

Hello folks,

This was a great read, thanks for a super tutorial on just exactly the topic I was searching for!

Can you tell me what the best strategy is for sending large amounts of data between a running FB application and an Arduino? Basically I want to update a group of member vars in a type instance with data constantly streaming in from the Arduino. Do I simply format the content of the variables as a string of text, serial print them, and then de-format them into variables again on reception? Or is there a better or less cumbersome way to do it?

Cheers,
Mike
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: FreeBasic communication with Arduino logic error?

Post by MrSwiss »

h4tt3n wrote:Do I simply format the content of the variables as a string of text, serial print them, and then de-format them into variables again on reception?
Yes, this should do.
h4tt3n wrote:Or is there a better or less cumbersome way to do it?
If cumbersome is meant to refer to string-splitting, there are some solutions available in this forum.
Since I'm to lazy currently (to search for them), just what I'm using:

Code: Select all

' (c) 2019-03-02, MrSwiss -- split a string into tokens (dyn. string array)

#Include "crt/string.bi"                ' needed for: SplitString()

Declare Function SplitString(ByRef As Const String, ByRef As Const String, () As String) As Long

Private Function SplitString( _         ' uses CRT's strtok() Function
    ByRef ssrc  As Const String, _      ' string to be searched
    ByRef chrs  As Const String, _      ' character(s), to search for
          res() As String _             ' result String array (ByRef, implicit!)
    ) As Long                           ' negative = error | >= 0 = OK
    Dim As Long     retv = 0            ' to hold return value

    If Len(chrs) = 0 Then retv -= 2     ' nothing to search for, set err
    If Len(ssrc) = 0 Then retv -= 1     ' no source string, set err
    If retv < 0 Then Return retv        ' return ERROR code (negative value)

    Erase(res)                          ' delete dyn. array's content (if any)
    Dim As String       s = ssrc        ' local variables: s = keeps ssrc
    Dim As ZString Ptr  psz = 0         ' result ptr (from strtok())
    Dim As UInteger     i = 0           ' counter, used as: array-index

    psz = strtok(s, chrs)               ' destroys s (must be reset! before reuse)
    While psz                           ' just to get required array size
        i += 1 : psz = strtok(0, chrs)  ' i - 1 = UBound(res)
    Wend

    retv = i - 1                        ' set arrays upper bound (return value)
    ReDim res(0 To retv)                ' size array (using retv)
    i = 0 : s = ssrc : psz = 0          ' reset i, s and psz (for next run)

    psz = strtok(s, chrs)               ' get first token (string-part)
    While psz                           ' run until psz is = 0
        res(i) = *psz                   ' assign token to array
        psz = strtok(0, chrs)           ' get next token (string-part)
        i += 1                          ' increment index
    Wend

    Return retv                         ' upper array bound (lower = 0 = default)
End Function
paul doe
Moderator
Posts: 1730
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: FreeBasic communication with Arduino logic error?

Post by paul doe »

@h4tt3n: Another possibility could be to send and receive binary blobs, and packing and unpacking them as required:

Code: Select all

'' Removed due to disinformation
This is faster but also have its drawbacks (and is no less cumbersome than parsing the data).

[Edit] There. I don't want anyone to be 'disinformed', the poor folks.
Last edited by paul doe on Jan 21, 2020 1:00, edited 3 times in total.
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: FreeBasic communication with Arduino logic error?

Post by MrSwiss »

Nothing wrong with the concept, however, the code is "disinformation".

Reason: no Arduino can deal with Double (data-type) since, Single is
the only supported floating point type (aka: float, in AVR-C).
coderJeff
Site Admin
Posts: 4313
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: FreeBasic communication with Arduino logic error?

Post by coderJeff »

Hi paul doe, my apologies. I've tried my best with Mr Swiss and I've asked a lot from many members, so I appreciate you hanging in there.
MrSwiss wrote:Nothing wrong with the concept, however, the code is "disinformation".

Reason: no Arduino can deal with Double (data-type) since, Single is
the only supported floating point type (aka: float, in AVR-C).
Hi MrSwiss. I thought we had a nice back-and-forth through email a while ago and I did try to offer some suggestions that might help you on the forums. But, it feels like I'm seeing the same old thing here and it's getting pretty tough to ask for more tolerance from everyone else.

A much better response here might have been "Careful, fbc's datatypes may not match Arduino's... always check the data types." That would actually be pretty good advice when transmitting data between any 2 systems, through file, network, serial, carrier pigeon (old joke, RFC1149)....

OK, how about the logical approach? Even if I convince everyone to ignore the way you say things (that's just your personality), I do believe you are wrong anyway, Unless I am misreading the docs. I don't have the hardware mentioned so couldn't say for sure: See: https://www.arduino.cc/reference/en/lan ... es/double/

Maybe double is 4 bytes or 8 bytes? I think it depends on hardware. Also, Arduino double/float docs don't say what format of floating point either though on the surface it does appear to be IEEE-754. I didn't find a reference to confirm. I didn't look very hard either.
paul doe
Moderator
Posts: 1730
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: FreeBasic communication with Arduino logic error?

Post by paul doe »

coderJeff wrote:Hi paul doe, my apologies. I've tried my best with Mr Swiss and I've asked a lot from many members, so I appreciate you hanging in there.
...
Oh? No need for apologies, really. It's not like I invented the technique or something, after all. Even a (mildly) trained chimpanzee, and MrSwiss, could eventually figure it out so I don't see what the big deal is.
coderJeff wrote: ...
OK, how about the logical approach? Even if I convince everyone to ignore the way you say things (that's just your personality), I do believe you are wrong anyway, Unless I am misreading the docs. I don't have the hardware mentioned so couldn't say for sure: See: https://www.arduino.cc/reference/en/lan ... es/double/

Maybe double is 4 bytes or 8 bytes? I think it depends on hardware. Also, Arduino double/float docs don't say what format of floating point either though on the surface it does appear to be IEEE-754. I didn't find a reference to confirm. I didn't look very hard either.
Indeed, it's hardware dependent: Arduino Reference: Double. So MrSwiss' response is, um, 'disinformed'?
marcov
Posts: 3454
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: FreeBasic communication with Arduino logic error?

Post by marcov »

Arduino Due is based on ARM technology, Atmel SAM3X8E, while the rest are pseudo 8-bitters.

I have the datasheet of the DUE here, and it doesn't say much about what FPU hardware it has. I assume that means it hasn't any, and typically other parts of its family, Cortex M3 doesn't seem to have it either.

So its higher speed and memory probably allows for more elaborate floating point emulation than the AVR ones, supporting both types.

Howver calling a 4-byte Single a Double is very confusing, and I can see where MrSwiss went wrong. It is counter-intuitive.

Anyway, the whole idea of single and double is that they stay the expected size. For a float type that scales with the architecture, C provides "float".

I can only guess why they did this, probably something historical, but IMHO it is not the best decision.

p.s. as for the whole discussion, a single to (real 64-bit) double is fairly easy afaik, just moving some bits. So if you want to keep the wire protocol universal (e.g. to use more precision with other hardware options), doing this even on Arduino AVR should be possible.
Post Reply