AT+ command problem with SIM20 transceiver

I am trying to set up an RF link using 2 SIM20 modules that I had in a drawer.

I can use them in the default transparent mode, but I want to set up a network ID etc, which is done by putting the devices into command mode, and writing to them with AT commands.

I remember before that I cant just send SIM.println("AT+SRDDATAR=?"); for example ( I am using NewSoftSerial ) as it is ignored

I played around with \n and \r and I can sort of get it working with the sketch below, but instead of returning the baud rate response, it returns either 33 or 161 or 67 in a random way each time I reset, (It should be a number from 0 to 7 ) followed by the "sent message" every 2 secs.

If I omit the SIM.print("\r\n"); before the AT command line, nothing is printed.

I have done a search on AT commands, and it looks like most times the serialPrintln is enough?

I dont want to send commands to change either unit if I cant get responses to keep an eye on whats happening, any ideas?

I have attached the AT commands manual for these units.

#include <NewSoftSerial.h>
#define RXPIN 14//   
#define TXPIN 15 // 
int   AC2DPin = 17;
int  serIn;  
#define SIMBAUD 9600
NewSoftSerial SIM(RXPIN, TXPIN);

void setup() 
{
  Serial.begin(9600); 
  pinMode(AC2DPin, OUTPUT);
  SIM.begin(SIMBAUD);
  digitalWrite(AC2DPin, LOW); //command mode
  delay(120);
  SIM.print("\r\n"); 
  SIM.println("AT+SRDUART=?");
  if (SIM.available() > 0) {   // get incoming byte:    
    Serial.println(" something available ");
    serIn = SIM.read () ;
    Serial.println(serIn  );   
  }     
  digitalWrite(AC2DPin, HIGH); // data mode 
}
void loop() 
{
  SIM.print("hellohello");
  Serial.println(" sent message ");   
  delay ( 2000 );
}

SIM20_AT_Command_Manual_V1.04.pdf (396 KB)

I have just done a range check and ran out of road, with one unit on my bench ( with I have just noticed, only a 120mm antenna ! ) and me going walkabout.
The furthest I could get was 170m away from my desk, through 4 houses and 3 walls, and reception was still solid.

Tommorow I will fit correct length antennas and do the open space test .

I am using SoftEasyTransfer.h and NewSoftSerial.h for data transfer ( at 9600 baud at the moment )
Apart from the error checking and package structure security of Easy transfer, I also have a security code of my own before either end responds.

I am using the modules in transparent mode, and everything except the signal strength ( RSSI) monitoring is fine, but it looks like I have to switch back to AT+ commmands to get them.

I can switch to command mode in the loop, and get the RSSI level with the AT command, but it doesnt go back to receiving when a I go back to data mode?

Hi,
from the manual, AT+SRDUART=? should give a response like +SRDUART: (0-6,0-5) \n OK -- it returns the device capabilities. The SRDUART? is what you are probably looking for -- it returns the device's current baud rate and mode.

The problem with the (random? maybe not) numbers is likely due to the fact that read() returns a byte, but you store it into an int, and print() assumes you want to print its numeric value. What you should see in this case are the ascii values of the characters in the response. Try changing the declaration of "int serIn" into char (or byte).

A further problem is that (in setup()) you only read once from SIM, so you are probably reading a character that was in the buffer before you sent the SRDUART command (it may happen that a \r\n gets an OK response, and often the command itself is echoed in the response). In order to get the whole message you would have to create something like a while(SIM.isAvailable()) loop, with various small delays to allow for new characters to arrive, until the buffer is empty. I think you get the idea.

Thanks for the ideas, I think my lack of understanding of the buffer has hit the nail on the head.

I did try declaring as a char and a byte, but having the check in the setup is not what I will be using on the project.

hen I run the code below , I get

+SRDRSSI: 224
OK

?and sometimes garbled charachters. The first 2 returns are ok, the third is garbled then its random. even if I change the array to 32 or 255.

So I think its the buffer thing. Why I wonder is the buffer size set to 128 ?
I cant remember where I grabbed this code from.

I dont need to take more than one reading before clearing the buffers and going back to the data mode for sending housekeeping data.

But every second or so I want to send all data. ( and in a response to a command from the base unit as an acknowledge )

if I get +SRDRSSI: 224 , in the char serInString array, ( consistantly ) I guess I can parse out the 3 bytes I need ( 2,2, & 4 in this case,) for sending back to the base unit. ( converted to an int )

I want to display in the base unit, the signal strength of both receivers to warn about sending the robot out of range.

#include <NewSoftSerial.h>
#define RXPIN 14//   
#define TXPIN 15 // 
#define SIMBAUD 9600
NewSoftSerial SIM(RXPIN, TXPIN);
int  serIn;             // var that will hold the bytes-in read from the serialBuffer
char serInString[128];  // array that will hold the different bytes  100=100characters;
// -> you must state how long the array will be else it won't work.
int  serInIndx  = 0;    // index of serInString[] in which to insert the next incoming byte
int  serOutIndx = 0;    // index of the outgoing serInString[] array;
const int AC2DPin = 17;  

void setup() 
{
  Serial.begin(9600);
  SIM.begin(SIMBAUD);
  pinMode(AC2DPin, OUTPUT);
  digitalWrite(AC2DPin, HIGH);
}

void loop () 
{

  digitalWrite(AC2DPin, LOW); //LOW for sending AT commands, High for transparent data mode
  delay(120);
  SIM.println("AT+SRDRSSI?");  //  
  SIM.print("\n");
  digitalWrite(AC2DPin, HIGH); 
  delay(10);
  readSerialString();
  //Serial.println ("------------ arduino is doing somenthing else ");  
  printSerialString();
  delay(1000);
}

void readSerialString () {
  int sb;   
  if(SIM.available()) {      
    while (SIM.available()){ 
      sb = SIM.read();             
      serInString[serInIndx] = sb;
      serInIndx++;

    }
  }  
}

void printSerialString() {
  if( serInIndx > 0) {
    //  Serial.print("Arduino memorized that you said: ");     

    for(serOutIndx=0; serOutIndx < serInIndx; serOutIndx++) {
      Serial.print( serInString[serOutIndx] );    //print out the byte at the specified index
      //serInString[serOutIndx] = "";            //optional: flush out the content
    }        
    //reset all the functions to be able to fill the string back with content
    serOutIndx = 0;
    serInIndx  = 0;
    Serial.println();
  }

}

?

Nice to see a meaningful message. Now I must immediately add that my initial suggestion of a while(available()) loop was just a quick and dirty way to diagnose the problem. The canonical implementation requires a state machine. For example, after sending a command you enter an "awaiting_response" state (set a boolean flag to true). At the beginning of each loop, check whether the state is true and take some characters from the buffer, then proceed with the other Arduino stuff:

void loop()
{
  if (awaiting_response) 
  {
    receive_response();
  }
  // do the normal stuff
}
void receive_response()
{
  while (SIM.available())
  { 
  // read from SIM and fill the buffer until you get OK; 
  // when you get OK change awaiting_response to false 
  // you shouldn't expect to read the whole response in a single function call, 
  // but you may discard unwanted characters while reading
  }
}

It will help to keep in mind that the command you send is echoed in the response, the OK is in a new line (and is followed by a newline character), and the value you need to parse starts from the : sign until the end of the line. So you don't actually need a large receive buffer because you can discard most of the strings. Consume all the characters in the response until the newline after OK even if you already parsed the value you need, otherwise they will stay in the buffer until the next response.

OK thanks I think I understand better, what changes awaiting_response back to true?
I presume I declare it as a boolean and true at the beginning?

My idea is, yes a boolean, set to false on startup, set to true immediately after sending the AT command, and reset to false after reading the newline following the OK in the response.

Then you will probably need another flag to signal the presence of data extracted from the message, to be transmitted to the control station. This starts false, is set to true after reading the response, and reset to false after the transmission is complete.

OK thanks I will give it a try later, its gone 6am and I will get to bed and sleep on it !

// read from SIM and fill the buffer until you get OK;
// when you get OK change awaiting_response to false

Can anyone give me a simple example of how to fill the buffer. I am used to VirtualWire doing this, but I am not using that here...

Hi, me again. Have a look at this post from Nick Gammon's forum Gammon Forum : Electronics : Microprocessors : How to process incoming serial data without blocking. It shows how you can read from a serial line, one character at a time, put it into a buffer at a certain position, and update the position to contain the next character.

The most important thing to be added to the code is in the process_data() function. Here I would compare the string with either SRDRSSI (this is the line containing the value, so it will need to be processed to extract the value from the buffer) or OK (this is the line ending the response, so it will reset awaiting_response to false).

Thanks,

I did look at Nicks site, I dont kow how I missed that. It loooks very good, I will go over it again when I get a minute. Crazy day !