martes, 25 de junio de 2013

Arduino GSM Shield tips & tricks


There are a lot of ways you can use a shield like this to improve your projects. I purchased it with the aim of mounting it into a rc car and controlling it from internet, including some video transmission to make a kind of remote car control panel, challenging project for me..., but that will worth another complete post, here I am focusing on GSM Shield.

I had never used a GSM shield and through the process of setting it up and testing I found some tips that I think that could be useful to other people facing this GSM Shield for the first time.



Power issues

This is a critical point, with almost every GSM shield a far as I could read. If you get erratic errors, your modem hangs out or your code stops forerever and you are powering it from USB then you are lucky because there are a lot of chances that all these problems will become solved when you change to another power source that is not limited to 500mA. 

In the Quectel M10 datasheet there are interesting comments about powering the modem: input voltage is between 3.4V and 4.5V, and current drawn can grow up to 2A at transmission bursts, causing voltage drops. A 100uF low ESR (Electrical Series Resistance) capacitor is recommended as near as possible to VBAT pin of the modem, MLCC (multilayer ceramic chip) capacitors are said to meet this low ESR and capacity requirements.

In this shield the powering circuit is the following (shield schematic):

GSM Shield powering circuit with LMZ12002 switching regulator

The circuit is based on the LMZ12002 switching regulator, which meets the requirements:
  • Up to 2A Output Current
  • Input Voltage Range 4.5V to 20V
  • Output Voltage Range 0.8V to 6V
  • Efficiency up to 92%

We see that the 100uF capacitor (C3225X5R0J107M) is placed near the output VBAT, it is MLCC and low ESR, with a 100nF in paralell, exactly as stated in Quectel datasheet. I though it could work, even powering just from USB (Vin not connected, 5V input to GSM shield is connected to Arduino 5V), with 500mA max current, but it didn't, it starts ok, registers in GSM and starts GPRS connection correctly, but after one or two TCP connections the modem hangs out and even the Serial connection from the arduino die (perhaps because the problem occurs at transmission, when more current is drawn, and before transmitting the interrupts of arduino are disabled with a cli() call in the SoftwareSerial library).

You probably noticed the big orange thing in the GSM shield, this is a 2200uF capacitor (592D228X96R3X2T20H), low ESR and MLCC also, a kind of mini-battery just at the input of the 5V from arduino, I suppose they put this to solve the problem of the low current coming from arduino. I think this is what let me open GSM, register GPRS and do a couple of HTTP POST before everything hangs out, but even with that little orange chocolate bar on top, it had not enough energy to go on.

In the circuit you see that power can come also from Vin pin to the LMZ12002 regulator, so that was my solution. With a 4xAA battery holder everything works fine:

GSM Shield poewerd with AA batteries

Here you can see the shield drawing 1.5A at the exact momment of transmission of an HTTP POST.
GSM Shield drawing 1.5A from 4xAA batteries

The 4xAA battery holder gives 6V aprox as input, that meets LMZ12002 input range, and is also enough for arduino. In my version (arduino UNO) it uses a 7805 regulator, that has 2V dropout voltage, so atmega is powered with 4V aprox, which it is not a inconvenience, nor for timing:

ATMEGA328P maximum frequency related to input V

nor for voltage levels, these are the serial logic level references for Quectel M10:

Quectel M10 serial interface logic levels



SoftwareSerial issues

GSM shield uses software serial to connect with arduino thorugh digital pins 2 and 3. In fact, these two pins, and digital 7 for reseting the modem from arduino are the only data connections between both, and that is a good thing, because it lets you almost every arduino pin free to do whatever you want and hardware serial remains free to connect arduino usb and debug while modem is working.
GSM shield connections to arduino

The problem with this is that SoftwareSerial is tricky when used with other libraries that deal with interruptions, it has problems with Servo library for example, and also here with GSM library. GSM3SoftSerial class in GSM library is almost a copy of SoftwareSerial class, and do the same with interruptions, it attachs functions to handle ALL external pin change interrupts PCINT0,1,2 of atmega328p, the same as SoftwareSerial, so if you try to compile a sketch that imports both libraries you will get an error like this because of that duplicity of interrupt vector attachments:

SoftwareSerial.cpp:312: multiple definition of `__vector_4'
GSM3SoftSerial.cpp:521: first defined here
SoftwareSerial.cpp:316: multiple definition of `__vector_5'
GSM3SoftSerial.cpp:525: first defined here
The error will be something like that, depending on what library you import first.

One possible solution to this is to change GSM library to attach interrupts just for the pins 2 and 3, that can be done several ways, these are two of them:

1. Using this very good library arduino-pinchangeint, but you should change all interrupt attachments in your code to use this library, it provides attachInterrupt function on PCINT0,1,2 just as with the built-in arduino attachInterrupt for INT0 and INT1. For example:
PCintPort::attachInterrupt(PIN7, myfunction_pin7int,CHANGE);
PCintPort::attachInterrupt(PIN5, myfunction_pin5int,RISING); 

2. As digital pins 2 and 3 are in the range of pins of PCINT2 (atmega328p has 3 external pin change interrupts PCINT0,1 and 2, each one for one port, so you have to distinguish inside the function attached which bit generated the interrupt..)

 D0-D7 = PCINT 16-23 = PCINT2 vector
 D8-D13 = PCINT 0-5 = PCINT0 vector
 A0-A5 (D14-D19) = PCINT 8-13 = PCINT1 vector

GSM library will work just attaching interrupt function to PCINT2 vector, so you can comment the rest of the attachments on GSM3SoftSerial  and comment PCINT2 attachment on SoftwareSerial, like this:

SoftwareSerial.cpp
#if defined(PCINT0_vect)
ISR(PCINT0_vect)
{
  SoftwareSerial::handle_interrupt();
}
#endif
#if defined(PCINT1_vect)
ISR(PCINT1_vect)
{
  SoftwareSerial::handle_interrupt();
}
#endif
/* disable this interrupt to enable them at GSM libray
#if defined(PCINT2_vect)
ISR(PCINT2_vect)
{
  SoftwareSerial::handle_interrupt();
}
#endif
*/

GSM3SoftSerial.cpp
/* use just the attachments needed for GSM shield
#if defined(PCINT0_vect)
ISR(PCINT0_vect)
{
  GSM3SoftSerial::handle_interrupt();
}
#endif
#if defined(PCINT1_vect)
ISR(PCINT1_vect)
{
  GSM3SoftSerial::handle_interrupt();
}
#endif
*/
#if defined(PCINT2_vect)
ISR(PCINT2_vect)
{
  GSM3SoftSerial::handle_interrupt();
}
#endif

I have tested and works fine, so with this trick you can mix both libraries in your project and avoid that limitation.


Debug mode

Just define the GSM class as this:

GSM GSMAccess = true;

and you will get printed into Serial the AT commands between atmega and the modem, very useful to see what is happening inside, for example I got my SIM locked and I was able to see that the modem was asking for the PUK thanks to this.

Here is the AT command reference, and here a more detailed document about TCP/IP treatment in the modem.



Client Timeout

Another important parameter to tune, at least in my case where GSM signal was a bit weak, is the Timeout for the GSMClient, by default it is set to 1000ms, but I changed it to 2000ms and thing where better, I stop getting TCP connections closed prematurely.


GSMClient client;
...
...
client.setTimeout(2000); //generic method for Stream class

12 comentarios:

  1. Hi Carlos.
    Thank you for your technical explanation, it was really interesting.

    I have a problem with my GSM Shield, unfortunatelly I don't find anything related on your post.

    Can you please take a look on my thread on Arduino forums?
    - http://forum.arduino.cc/index.php?topic=183135.0

    Thank you!

    ResponderEliminar
  2. Hi Carlos, congrats for this excellent post.

    Could you please add a complete example as how to use the PinChangeInt option? I have been trying to compile using your approach without success. Many thanks in advance.

    ResponderEliminar
    Respuestas
    1. Hi Simon, you can find some complete examples here: https://code.google.com/p/arduino-pinchangeint/wiki/Usage

      Eliminar
    2. Thanks Carlos, I got it running now. Problem still with the fact that is quite unstable. My setup sends an API to Pushingbox every two minutes and after some time working fine (from hors to days) it suddenly stops transmitting. Very frustrating / disappointing.

      Eliminar
    3. Yes it was the same in my case, I think the powering to the board is critical, a battery able to provide high busrt currents, perhaps some lipo... what kind of battery are you using?

      Eliminar
    4. Hi Carlos, no battery at all, I'm using a 2.5 A 9 Volt power supply. I've even implemented the modem Emergency Pin reset suggestion posted by AndersHedberg on the Arduino forum (http://forum.arduino.cc/index.php?topic=159063.msg1245917#msg1245917) which keeps it working for a longer period but still hangs after some time. I'm considering now to try a 555 based Watch Dog circuit to reset the whole setup every a couple of minutes. Pretty low tech...

      Eliminar
  3. arduino gsm gprs library: http://elecfreaks.com/store/download/datasheet/wireless/GSM_Shield2.zip

    ResponderEliminar
  4. Hi Keven can you elaborate (explain) about your post?

    Thanks, Simon

    ResponderEliminar
  5. Do you have any idea why this problem could occur:

    http://forum.arduino.cc/index.php?topic=282519.0

    Thanks.

    ResponderEliminar
  6. Hi Carlos. It works like a charm on Arduino Uno. But what should you do to make it work on Arduino Mega? Thank you!

    ResponderEliminar