Recent

Author Topic: One-way serial communication example using Synaser & Arduino Nano  (Read 2467 times)

Aruna

  • Hero Member
  • *****
  • Posts: 568
Re: One-way serial communication example using Synaser & Arduino Nano
« Reply #15 on: September 25, 2024, 04:04:52 pm »
Specifically, they're on the AVR microcontroller pins being used as the serial port, which in the case of older Arduino models is followed by a chip (either a smaller AVR or an FTDI knockoff) providing a USB port for the PC. So as you observe, they just blink.
LED_BUILTIN is commonly connected to digital pin 13 on most Arduino boards, but some models (like MKR series boards) have it connected to other pins (like digital pin 6).

Aruna

  • Hero Member
  • *****
  • Posts: 568
Re: One-way serial communication example using Synaser & Arduino Nano
« Reply #16 on: September 25, 2024, 04:12:04 pm »
O, it's about the led L.
That should be LED_BUILTIN and be on the board.
https://flaviocopes.com/arduino-built-in-led/
Yes  :D

MarkMLl

  • Hero Member
  • *****
  • Posts: 8111
Re: One-way serial communication example using Synaser & Arduino Nano
« Reply #17 on: September 25, 2024, 04:30:43 pm »
Right. I suggest you start (on the PC side) with the extremely simple terminal emulator I've given you, if there's bits you don't understand then use the traditional neurophysiologist's (aka Kennedy) technique.

Attached are some basic demos, the double-tap one should be self-explanatory but double-tap-and-hello has an extra include line (to recover board info etc.) that you can comment out until you've found your way around.

The third directory contains various things to exercise an Arduino with both serial and I2C comms, where the host was assumed to be an RPi.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

ccrause

  • Hero Member
  • *****
  • Posts: 988
Re: One-way serial communication example using Synaser & Arduino Nano
« Reply #18 on: September 25, 2024, 10:18:27 pm »
I haven't noticed a Pascal version of the Arduino code. Below a Pascal version that configures a serial connection for 9600 baud, 8N1.  It assumes a clock frequency of 16MHz.
Code: Pascal  [Select][+][-]
  1. program firmware;
  2.  
  3. {$mode ObjFPC}
  4.  
  5. { Demo program to switch an LED on or off based on text commands received
  6.   over serial.  This code is written for an atmega328p and should be compatible with the
  7.   Arduino Uno/Nano boards.
  8.  
  9.   Written for the Free Pascal compiler.  Compiler command line
  10.   (requires ppcrossavr compiler to be installed):
  11.   $ fpc -Tembedded -Pavr -Wpatmega328p -O3 firmware.pp
  12.   Note on Linux it may be necessary to specify the binutils prefix: -XPavr-
  13.  
  14.   Upload firmware.hex to Arduino:
  15.   $ avrdude -P /dev/ttyACM0 -p m328p -c arduino -v -e -U flash:w:firmware.hex }
  16.  
  17. type
  18.   // State machine for parsing input strings
  19.   TCmdState = (csNone, csO, csOf, csOff, csOn);
  20.  
  21. const
  22.   F_CPU = 16000000;
  23.   baud = 9600;
  24.   LEDPin = 1 shl 5;
  25.  
  26. var
  27.   c: char;
  28.   state: TCmdState;
  29.   LEDport: byte absolute PORTB;
  30.   LEDdir: byte absolute DDRB;
  31.  
  32. procedure uartInit;
  33. begin
  34.   // Baud rate setting
  35.   // Formula for X2 option with rounding
  36.   UBRR0 := ((F_CPU + 4*baud) shr 3) div baud;
  37.   // Set U2X as specified
  38.   UCSR0A := 1 shl U2X0;
  39.   // Enable receiver and transmitter
  40.   UCSR0B := (1 shl RXEN0) or (1 shl TXEN0);
  41.   // Set frame format: 8data, 1stop bit, no parity
  42.   UCSR0C := (3 shl UCSZ0);
  43. end;
  44.  
  45. procedure uartTransmitChar(const data: byte);
  46. begin
  47.   // Wait for empty transmit buffer
  48.   while ((UCSR0A and (1 shl UDRE0)) = 0) do;
  49.   // Put data into buffer, sends the data
  50.   UDR0 := data;
  51. end;
  52.  
  53. procedure uartTransmitString(const s: shortstring);
  54. var
  55.   c: char;
  56. begin
  57.   for c in s do
  58.     uartTransmitChar(ord(c));
  59. end;
  60.  
  61. function uartReceive: char;
  62. begin
  63.   // Wait for data to be received
  64.   while ((UCSR0A and (1 shl RXC0)) = 0) do;
  65.   // Get and return received data from buffer
  66.   result := char(UDR0);
  67. end;
  68.  
  69. begin
  70.   // Switch LED pin to output
  71.   LEDdir := LEDPin;
  72.   uartInit();
  73.  
  74.   // Transmit help message
  75.   uartTransmitString('Enter any of the following commands:'#10);
  76.   uartTransmitString('  on  - switch LED on'#10);
  77.   uartTransmitString('  off - switch LED off'#10);
  78.  
  79.   state := csNone;
  80.   repeat
  81.     c := uartReceive();    // blocking
  82.  
  83.     // Feed character into state machine
  84.     case state of
  85.       csNone:
  86.       begin
  87.         if c in ['o', 'O'] then
  88.           state := csO
  89.         else
  90.           state := csNone;
  91.       end;
  92.  
  93.       csO:
  94.       begin
  95.         if c in ['n', 'N'] then
  96.           state := csOn
  97.         else if c in ['f', 'F'] then
  98.           state := csOf
  99.         else if not(c in ['o', 'O']) then // Ignore repeated 'o' characters
  100.           state := csNone;
  101.       end;
  102.  
  103.       csOf:
  104.       begin
  105.         if c in ['f', 'F'] then
  106.           state := csOff
  107.         else
  108.           state := csNone;
  109.       end;
  110.     end;
  111.  
  112.     if state > csOf then
  113.     begin
  114.       if state = csOff then
  115.         LEDport := LEDport and not(LEDPin)
  116.       else
  117.         LEDport := LEDport or LEDPin;
  118.  
  119.       state := csNone;
  120.     end;
  121.   until false;
  122. end.

Command processing is done using a simple finite state machine which hopefully makes it somewhat robust against junk input.

Aruna

  • Hero Member
  • *****
  • Posts: 568
Re: One-way serial communication example using Synaser & Arduino Nano
« Reply #19 on: September 26, 2024, 04:58:54 am »
Hi, I managed to get the IDE to talk to the Arduino nano serial port and got the nano to send back data to the IDE. It is getting late here been a very long day for me. I will post the full source code and any relevant findings in the morning. @MarkMLI is there a reason why you use (* comment *)   over {} or // ? Also Mark you know the console we have in the ide? If I wanted a console in my application how easy or difficult will it be to implement? I am too tired right now to search through the Lazarus source, maybe tomorrow.

MarkMLl

  • Hero Member
  • *****
  • Posts: 8111
Re: One-way serial communication example using Synaser & Arduino Nano
« Reply #20 on: September 26, 2024, 08:38:32 am »
Hi, I managed to get the IDE to talk to the Arduino nano serial port and got the nano to send back data to the IDE. It is getting late here been a very long day for me. I will post the full source code and any relevant findings in the morning. @MarkMLI is there a reason why you use (* comment *)   over {} or // ?

When I started Pascal (**) was preferred, and {} represents set contents in Modula-2. In practice I "Sloane" comments that I want to be permanent in part as an indication that I've given them some thought and tried to choose my words carefully. Some of the comment layout is mandated by the IDE's parsing to make popups etc.

Quote
Also Mark you know the console we have in the ide? If I wanted a console in my application how easy or difficult will it be to implement? I am too tired right now to search through the Lazarus source, maybe tomorrow.

You'll find that the IDE console doesn't much like (unless something's improved a lot since I hacked it last) individual characters: it tends to insert newlines between them.

Neither Lazarus nor Delphi has good inherent support for "shell style" scrolling applications. There's various terminal emulator components that you can use, I've got my own but not being a particularly accomplished GUI programmer I'm not comfortable sharing it (it does the reasonably specialised things I need, and that's about it).

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

avra

  • Hero Member
  • *****
  • Posts: 2532
    • Additional info
Re: One-way serial communication example using Synaser & Arduino Nano
« Reply #21 on: September 27, 2024, 03:36:07 pm »
I haven't noticed a Pascal version of the Arduino code.
Could you please update the wiki?
https://wiki.freepascal.org/Arduino#Minimal_Arduino_FPC_serial_example
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

Aruna

  • Hero Member
  • *****
  • Posts: 568
Re: One-way serial communication example using Synaser & Arduino Nano
« Reply #22 on: September 27, 2024, 03:45:17 pm »
I haven't noticed a Pascal version of the Arduino code.
Could you please update the wiki?
https://wiki.freepascal.org/Arduino#Minimal_Arduino_FPC_serial_example
Hi @avra, absolutely can do, but I have used the Arduino nano serial port as a 'ordinary file' and I did manage to get things working and @MarkMLI was not happy with what I did ( understandably) but try as I might I could not get Synapse, Synaser, and friends to become friends with the Nano's serial port. So I resorted to old-fashioned tried and tested ways and things started working.

So before updating the wiki I want a second opinion from everyone out there that what I have done is ok and acceptable content for the wiki. I will post a zip with the full source code ( Still trying to wake up :-)
« Last Edit: September 27, 2024, 03:54:24 pm by Aruna »

dseligo

  • Hero Member
  • *****
  • Posts: 1449
Re: One-way serial communication example using Synaser & Arduino Nano
« Reply #23 on: September 27, 2024, 05:44:33 pm »
I haven't noticed a Pascal version of the Arduino code.
Could you please update the wiki?
https://wiki.freepascal.org/Arduino#Minimal_Arduino_FPC_serial_example
Hi @avra, absolutely can do, but I have used the Arduino nano serial port as a 'ordinary file' and I did manage to get things working and @MarkMLI was not happy with what I did ( understandably) but try as I might I could not get Synapse, Synaser, and friends to become friends with the Nano's serial port. So I resorted to old-fashioned tried and tested ways and things started working.

Avra was referring to ccrause's code in reply #18. That code is for AVR side (Arduino board), not PC side.

Aruna

  • Hero Member
  • *****
  • Posts: 568
Re: One-way serial communication example using Synaser & Arduino Nano
« Reply #24 on: September 28, 2024, 03:10:34 am »
I haven't noticed a Pascal version of the Arduino code.
Could you please update the wiki?
https://wiki.freepascal.org/Arduino#Minimal_Arduino_FPC_serial_example
Hi @avra, absolutely can do, but I have used the Arduino nano serial port as a 'ordinary file' and I did manage to get things working and @MarkMLI was not happy with what I did ( understandably) but try as I might I could not get Synapse, Synaser, and friends to become friends with the Nano's serial port. So I resorted to old-fashioned tried and tested ways and things started working.

Avra was referring to ccrause's code in reply #18. That code is for AVR side (Arduino board), not PC side.
My apologies, I misunderstood. Thank you for clarifying :-)

ccrause

  • Hero Member
  • *****
  • Posts: 988
Re: One-way serial communication example using Synaser & Arduino Nano
« Reply #25 on: September 28, 2024, 04:07:32 pm »
Below a plain program that uses the serial unit for serial data transmission on the PC side.  Tested with the previous AVR firmware code.

A note about the Arduino board reset from DTR signal: The serial port should first be opened to obtain a handle before a call to SerSetDTR can be made.  The OS/USB driver will however assert the DTR (and other signal lines) when the serial port is opened, therefore the initial behaviour is determined be the previous settings of that port.  Also, the DTR output of the Arduino Uno/Nano USB-serial converters are inverted, so setting DTR to true/high results in a low signal to the reset circuitry which then causes a reset.  Thus to prevent  a board reset when opening the serial port on the PC, set DTR to true (3rd command line argument set to 1).

Code: Pascal  [Select][+][-]
  1. program serialtransmitter;
  2.  
  3. uses
  4.   serial, sysutils;
  5.  
  6. procedure help;
  7. begin
  8.   WriteLn('Usage:');
  9.   WriteLn('  test <portname> <baud> {DTR}');
  10.   WriteLn('    <port> - required: full name of serial port e.g. /dev/ttyUSB0 or com3');
  11.   WriteLn('    <baud> - required: baud rate of connection e.g. 9600');
  12.   WriteLn('    {DTR}  - optional: assert logical state of DTR line, 0 or 1');
  13.   WriteLn;
  14. end;
  15.  
  16. var
  17.   ser: THandle;
  18.   s: string;
  19.   baud, i: integer;
  20.   doSetDTR, DTRsetting: boolean;
  21.  
  22. begin
  23.   if ParamCount < 2 then
  24.   begin
  25.     help;
  26.     Exit;
  27.   end;
  28.  
  29.   s := ParamStr(2);
  30.   val(s, baud, i);
  31.   if i <> 0 then
  32.   begin
  33.     WriteLn('Invalid argument for baud. Value must be a valid integer.');
  34.     help;
  35.     Exit;
  36.   end;
  37.  
  38.   if ParamCount > 2 then
  39.   begin
  40.     if (ParamStr(3) = '0') or (ParamStr(3) = '1') then
  41.     begin
  42.       doSetDTR := true;
  43.       DTRsetting := ParamStr(3) = '1';
  44.     end
  45.     else
  46.     begin
  47.       WriteLn('Invalid argument for DTR. Value must be 0 or 1');
  48.       help;
  49.       Exit;
  50.     end;
  51.   end
  52.   else
  53.     doSetDTR := false;
  54.  
  55.   s := ParamStr(1);
  56.   ser := SerOpen(s);
  57.   if ser > -1 then
  58.   begin
  59.     WriteLn('Usage: type command followed by enter key.');
  60.     WriteLn('Type exit to exit');
  61.     WriteLn;
  62.  
  63.     SerSetParams(ser, baud, 8, NoneParity, 1, []);
  64.  
  65.     // Set DTR to false
  66.     if doSetDTR then
  67.       SerSetDTR(ser, DTRsetting);
  68.  
  69.     repeat
  70.       // Wait for data to be entered
  71.       ReadLn(s);
  72.  
  73.       if CompareText(s, 'exit') = 0 then
  74.         Break;
  75.  
  76.       if SerWrite(ser, s[1], Length(s)) <> Length(s) then
  77.         WriteLn('*Error transmitting data: ', GetLastOSError);
  78.     until false;
  79.     SerClose(ser);
  80.   end
  81.   else
  82.     WriteLn('Error ', GetLastOSError, ' opening serial port ', s);
  83. end.

 

TinyPortal © 2005-2018