Communication with a module - an advice

Go To Last Post
4 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello, 

 

I'm working with AVR mcu and I'm communicating with a wifi module (ESP8266) via uart that has the ability to act as a server, hence to send and receive messages from other clients. 

I encounterd a problem that has difficulty solving.
The situation is that I want to send a message from the MCU to the outside world (other clients) via a WIFI module.
For that, I need to send first this command :
AT+CIPSEND=<client id>,<length of the string I want to send>
then I need to wait for a "OK" response from the wifi module and just after that I can send my message and also wait for "SEND OK" message as a response.
So in conclusion I need 4 steps :

1. send a request to some client
2. wait for OK response
3. send the wanted message
4. get the SEND OK response

I have a function that makes me this but I don't want it to be waiting for the OK response / SEND OK (in a while loop for example) cause it causes me a delay.

What can I do in order to minimize delay the OK ? 

 

I would be glad to hear tips
 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

you could enable the UART Rx Interrupt and check for "OK" from the service routine:

void init()
{
    UCSRB |= (1 << RXCIE); //Enable UART RXC Interrupt
    sei(); //Enable interrupts
    ...
}

ISR(USART_RXC_vect)
{
   char byte;
   byte = UDR;
   ...
}

also give this a read if you're new to interrupts.

Last Edited: Tue. Dec 15, 2015 - 11:17 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

kobidon wrote:
What can I do in order to minimize delay the OK ?

That is a big question.

 

First, Google indicates to me that you might be referring to an ESP8266?  If so (and I'd speculate that the following will be true for most AT-command devices) then you left something very useful out of your step summary:  CR-LF after each command, and apparently most [all?] responses are preceded and followed by CR-LF.  This is a great aid to knowing when to proceed.

 

Short answer:  State machines.  If it were my app I'd spend some time studying and charting the needed commands and responses for orthogonality--I'd group those that have a similar structure to minimize parsing routines.  Note the "needed" in there -- if the command set has dozens of commands/responses but the app only needs three then the job is easier.  E.g. A ModbusRTU master only needs to implement the commands needed, which might only be one--Read Register.  Then Modbus takes 100 words, but a full implementation takes several thousand.

 

I'd start with two levels: "SEND" routine, with your built string.  (Or, you might pass a command code and have the routine build and send the string.)  Then, the "RECEIVE" routine would gather the response.  Let's say it just knows how to gather until the trailing CR-LF is seen.  One important thing here is a drop-dead timer that starts after the command is sent.  Commonly, I restart that timer when each character of the response is received.  If the timer expires -- no well-formed message received within 10ms or 100ms or whatever -- then that is a failure and the transaction needs to be restarted.

 

A state machine is used, and for these primary purposes when a well-formed response is received, it is parsed into the component parts and there is the concept of "expecting".  The simplest might be the CR-LF-"OK"-CR-LF.  when seen, then the app proceeds to the next applicable state.

 

So there are no delays anywhere.  The app is free to watch and debounce buttons, gather ADC readings, blink lights, whatever.

 

Your device is fairly elaborate, so I'd make the multi-level as outlined above.  A simpler case that I use for an RFID reader uses a state machine character-by-character.  The link: https://www.avrfreaks.net/comment... Note "Other "external" code times out and resets the state machine in the case of malformed messages."  That is the timer I mentioned above--IMO/IME this is a very important part of this type of communication.  Every 10ms:

// ***********
// RFID Reader Commo State Machine Timer
// ***********
//
//	If no activity for this many ticks, go to the "idle" state to restart
//	the state machine.
//
		if (rfid_ticks > 0)
			{
			if (--rfid_ticks <= 0)
				{
				rfid_state = RFID_IDLE;
				clear_rx_buffer0();
				}
			}

...and you see the timer being activated when the first character received in the linked code above:

		switch (rfid_state)
			{
			case RFID_IDLE:
				if (scratch == 0x02)	// looking for STX when idle--should be the start of message
					{
					rfid_state = RFID_STX;
					rfid_buffer[rfid_state++] = scratch;
					rfid_ticks = RFID_TICKS; // start the countdown timer
					}
				break;

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
Short answer:  State machines.  

 

Absolutely!!

 

https://www.avrfreaks.net/comment...

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...