📜 ⬆️ ⬇️

Based on "Processing lines on Arduino"

Read today a post on Geektimes , and I want to share the experience. I do not want to discuss the pros and cons of the Arduino, but the conditions of the project in which I applied the following are to be done under it. Essence - you need to provide the user with a terminal to control the device. Appropriately, not a small part of the work is working with strings. To apply or not the proposed solution - let everyone decide for himself.

I decided to refuse the String class: linker error . It appeared to me only when I tried to use the String class.

What was required? Information output and processing of the lines entered by the user. For example:
Ethernet controller - ok
STATIC mode
> time
2015-11-16 22:35:27

Actually, it is necessary to compare the drains. No, you first need to break the text into fragments with a separator (for example, a space), but then still compare the lines. Since the teams were "one, two - and obchlsya", then the text breakdown into fragments removed. Because of the above error, the String class could not be used, how else could it be? Arduino uses the AVR-libc library, it is reasonable to refer to it first.
What do we have?

  1. stdlib.h - functions of mutual conversion of numbers and strings (in both directions).
  2. string.h - functions for working with strings. Our main interest.
  3. stdio.h is standard input / output functions.

This is not limited to functional. Mentioned that is associated with the task.
')
So, I recommend number 1 for familiarization - it will suddenly come in handy separately somewhere. By itself, it is used only for the operation of string.h .

No. 2 - we use the memset functions to fill or clear the buffer, memcmp - for comparison. I do not use strcmp , since I need to explicitly limit the length of the fragment being compared. №3 - for format reading and output: sprintf , sprint_P , sscanf , sscanf_P . Functions with the _P suffix are different in that the format string is taken from the memory of the PROGMEM programs, also known as the F () macro in the Arduino libraries.

By the way
By the way, if you fully implement the I / O functions of a separate character getc and putc , you will get standard input, output, error streams and for working with files, if you have any. You can often get by with overriding putchar () and getchar () macros that work with standard input and output.

My string comparison looks like this:

if ( memcmp(str ,"statlist" ,8)==0 ) { // your code here } 

Perhaps, it is worth making a reservation that the beginnings of lines are compared. To search for fragments, you can use memmem .

strings for C
the strings for C are str , they are char * - this is a reference to the beginning of the char sequence, the last of which is 0x00 . So, they need to be placed somewhere. For example, in an array. Or use malloc , calloc , free . That does not allow to make mistakes implies shifting responsibility on the programmer for their placement and control of length .

That is, the search team may look like this:

  if ( memcmp(str ,"statclear", 9)==0 ) { memset(journal, 0, sizeof(jrn_rec_t)*JRN_REC_NUM ); Serial.println( F("ok") ); }else if ( memcmp(str ,"statlist" ,8)==0 ) { funcStatlist(); }else if ( memcmp(str ,"cfgshow", 7)==0 ) { funcCfgShow(); }else if ( memcmp(str ,"timeset", 7)==0 ) { funcTimeSet( str); // setup date and time YYYY-MM-DD hh:mm:ss }else if ( memcmp(str ,"cfgset", 6)==0 ) { funcCfgSet( str); //funcPingdel( str); }else if ( memcmp(str ,"time", 4)==0 ) { funcTime(); // print date and time from RTC }else if ( memcmp(str ,"help", 4)==0 ) { // print short help Serial.println( F(" help\r\n statlist statclear\r\n time timeset\r\n cfgshow cfgset") ); }else{ Serial.print( F("unknow cmd> ")); Serial.println( str); } 

Unobvious moment
Commands, they are the same lines, with a greater length should go first in the given fragment. Think about why?

I “assemble” strings as follows: I read bytes from the port until the allowed length of the string is exceeded or until one of the newline characters \ r or \ n is encountered.

reading line
It would be better to refine ... As long as it is. Called all the time in the main ring. If there is no work - as fast as possible to exit, return false . If you typed a new line - true .

 bool readln( HardwareSerial &uart, char *outbuf) // return true when find CR, LF or both and if size limit { static char mybuf[SBUF_SZ] = { 0 }; static char idx = 0; while (uart.available()) { if ( uart.peek()!= '\r' && uart.peek()!= '\n' ) { mybuf[ idx++ ] = uart.read(); } else {//  CR uart.read(); if ( uart.peek()=='\n' || uart.peek()=='\r' ) uart.read(); if ( idx == 0 ) { return 0; } mybuf[ idx++ ] = '\0'; //  0 memcpy( outbuf, mybuf, idx); //  idx = 0; return 1; } if ( idx >=(SBUF_SZ-1) ) { //      mybuf[ SBUF_SZ-1 ] = '\0'; //  0 memcpy( outbuf, mybuf, 32); //  idx = 0; return 1; } } return 0; } 


Format I / O is also very useful. For example, parsing a string with a given date and time looks like this:
 sscanf_P(str, (const char *)F("%*s %d-%d-%d %d:%d:%d"), &y, &m, &d, &hh, &mm, &ss) 

Obtaining a string for IP output:

 sprintf_P(buff, (const char *)F("Your IP: %d.%d.%d.%d"), ip[0], ip[1], ip[2], ip[3]); 

More information about the format string can be read, for example, here scanf and here (printf).

That's all. I hope this material will help someone to get rid of the Arduino, or just better and write their programs in less time. But a more typical situation is to circumvent the limitations of wiring .

Thanks to the author of the original article, at least for forcing me to collect this material.

Source: https://habr.com/ru/post/357892/


All Articles