Sim800L lag/delay before incoming calls are visible to arduino - arduino

I use SIM800L GSM module to detect incoming calls and generally it works fine. The only problem is that sometimes it takes up to 8 RINGS before the GSM module tells arduino that someone is calling (before RING appears on the serial connection). It looks like a GSM Network congestion but I do not have such issues with normal calls (I mean calls between people). It happens to often - so it cannot be network/Provider overload. Does anybody else had such a problem?
ISP/Provider: Plus GSM in Poland
I don't put any code, because the problem is in different layer I think

sorry that I didn't answer earlier. I've tested it and it turned out that in bare minimum code it worked OK! I mean, I can see 'RING' on the serial monitor immediately after dialing the number. So it's not a hardware issue!
//bare minimum code:
void loop() {
if(serialSIM800.available()){
Serial.write(serialSIM800.read());
}
if(Serial.available()){
serialSIM800.write(Serial.read());
}
}
In my real code I need to compare calling number with the trusted list. To do that I saved all trusted numbers in the contact list on the sim card (with the common prefix name 'mytrusted'). So, in the main loop there's if statement:
while(mySerial.available()){
incomingByte = mySerial.read();
inputString += incomingByte;
}
if (inputString.indexOf("mytrusted") > 0){
isTrusted = 1;
Serial.println("A TRUSTED NUMBER IS CALLING");
}
After adding this "if condition" Arduino sometimes recognize trusted number after 1'st call, and sometimes after 4'th or 5'th. I'm not suspecting the if statement itself , but the preceding while loop, where incoming bytes are combined into one string.
Any ideas, what can be improved in this simply code?

It seems, I found workaround for my problem. I just send a simple 'AT' command every 20 seconds to SIM800L (it replies with 'OK' ). I use timer to count this 20 seconds interval (instead of simply delay function)
TimerObject *timer2 = new TimerObject(20000); //AT command interval
....
timer2->setOnTimer(&SendATCMD);
....
void SendATCMD () {
mySerial.println("AT");
timer2->Stop();
timer2->Start();
}
With this simple modification Arduino always sees incoming call immediately (after 1 ring)

Related

HC-SR04P reading errors

In my project I need to measure distances up to 3-4m, so I am using a HC-SR04P sensor hooked up to an ESP32 dev board.
The code is written without any third-party library (was inspired by a very simple HC-SR04 arduino library, though), in plain C, within a project created from the ESP32 eclipse IDF plugin; no extra libraries or arduino code; just the RTOS.
Everything works fine when the device boots and measurements are pretty accurate, but after a while (can't say exactly what triggers this), the sensor/devboard circuit (can't say which) starts behaving strangely : after the TRIG pulse, the ECHO pin does not go HIGH within a reasonable 1s timeout, and no measurement is performed.
Once this happens, no new measurement is performed again unless reboot/power on; it looks like something happens and somehow there is a faulty state either for the sensor or within the communication code.
A couple of observations :
sensor is the right version to be powered at 3.3V.
HC-SR04P uses GPIO2 and GPIO4 for TRIG and ECHO.
measurements are not required to be frequent, hence the 30s timer for the measurement task.
at power on, everything works fine.
after reset by dev board micro-switch, everything works correctly again.
when timeout occurs, re-init the sensor (settings up GPIOs, etc.), but nothing happens; still timeouts.
For reference, the timing function is below (the HCSR04_Info struct holds only pin and measurement data); it is called from a timed task every 30s.
uint32_t hcsr04_timing(HCSR04_Info* pDevice)
{
// TRIG pulse for 10ms
gpio_set_level(pDevice->trig, 1);
ets_delay_us(10);
gpio_set_level(pDevice->trig, 0);
pDevice->startMicros = esp_timer_get_time();
// wait for the echo pin HIGH or timeout
while ((!gpio_get_level(pDevice->echo)) && (esp_timer_get_time() - pDevice->startMicros) <= pDevice->timeout);
if (!gpio_get_level(pDevice->echo)) {
pDevice->status = STATUS_OFFLINE;
ESP_LOGE(TAG, "hcsr04_timing timeout (1)");
return 0;
}
pDevice->startMicros = esp_timer_get_time();
// wait for the echo pin LOW or timeout
while ((gpio_get_level(pDevice->echo)) && (esp_timer_get_time() - pDevice->startMicros) <= pDevice->timeout);
if (gpio_get_level(pDevice->echo)) {
pDevice->status = STATUS_OFFLINE;
ESP_LOGE(TAG, "hcsr04_timing timeout (2)");
return 0;
}
pDevice->status = STATUS_ONLINE;
pDevice->endMicros = esp_timer_get_time();
return pDevice->endMicros - pDevice->startMicros;
}
Any help is appreciated. Thank you.
This does not generate a pulse of 10 ms; it's 10 us. Probably takes your device into an undetermined state eventually.
// TRIG pulse for 10ms
gpio_set_level(pDevice->trig, 1);
ets_delay_us(10);
gpio_set_level(pDevice->trig, 0);
The comment in the header file where ets_delay_us() is defined says: In FreeRTOS task, please call FreeRTOS apis.
Anyway, use delay(10) if in Arduino-land; or vTaskDelay(pdMS_TO_TICKS(10)) if in FreeRTOS-land.
Following up on campescassiano suggestions on overflow, the solution finally presented itself. Not really an overflow in the exact sense of the problem, but closely related.
It's finally a stupid bug in the code, so please close or delete the question if appropriate.
The problem was that pDevice->startMicros was defined as an uint32_t (probably because of a copy/paste or bad habit error), while esp_timer_get_time() returns microseconds as an uint64_t.
So it 'overflows' at about 1h 11m 34s (which is about 232 microseconds) after boot, and timeout calculations become off since (esp_timer_get_time() - pDevice->startMicros) will obviously be an uint64_t.
Because of that (esp_timer_get_time() - pDevice->startMicros) <= pDevice->timeout will always be false after 1h 11m 34s, so the loop breaks before getting an ECHO input.

Reading a long text from GPRS Shield with Arduino

I am having hell with this and I know it is probably really simple. I am trying to read a text message from my Seeed GPRS shield. I have the shield setup as a software serial and I am displaying the information received from the GPRS to the serial monitor. I am currently sending all AT commands over serial while I work on my code. To display the data from the software serial to the serial monitor, I am using the following code.
while(GPRS.available()!=0) {
Serial.write(GPRS.read());
}
GPRS is my software serial obviously. The problem is, the text is long and I only get a few characters from it. Something like this.
+CMGR: "REC READ","1511","","13/12/09,14:34:54-24" Welcome to TM eos8
This text is a "Welcome to T-Mobile" text that is much longer. The last few characters shown are scrambled. I have done some research and have seen that I can mod the serial buffer size to 256 instead of the default 64. I want to avoid this because I am sure there is an easier way. Any ideas?
Have you tried reading into a character array, one byte at a time? See if this helps:
if (GPRS.available()) { // GPRS talking ..
while(GPRS.available()) { // As long as it is talking ..
buffer[count++]=GPRS.read();     
// read char into array
if(count == 64) break; // Enough said!
}
Serial.write(buffer,count); // Display in Terminal
clearBufferArray();
count = 0;
}
You need to declare the variables 'buffer' and 'count' appropriately and define the function 'clearBufferArray()'
Let me know if this helps.
Looks like this is simply the result of the lack of flow control in all Arduino serial connections. If you cannot pace your GPRS() input byte sequence to a rate that guarantees the input FIFO can't overflow, then your Serial.write() will block when the output FIFO fills. At that point you will be dropping new GPRS input bytes on the floor until Serial output frees up more space.
Since the captured output is apparently clean up to about 64 bytes, this suggests
a) a 64 byte buffer,
b) a GPRS data rate much higher than the Serial one, and
c) that the garbage data is actually the occasional valid byte from later in the sequence.
You might confirm this by testing the return code from Serial.write. If you get back zero, that byte is getting lost.
If you were using 9600 for Serial and 57600 for GPRS, I would expect somewhat more than 64 bytes to come through before the output gets mangled, but if the GPRS rate is more than 64x the Serial rate, the entire output FIFO could fill up within a single output byte transmission time.
Capturing to an intermediate buffer should resolve your issue, as long as it is large enough for the whole message. Similarly, extending the size of either the source (in conjunction with testing the Serial.write) or destination (without any additional code) FIFOs to the maximum datagram size should work.
I've had the same problem trying to read messages and get 64 characters. I overcame it by adding a "delay(10)" in the loop calling the function that does the read from the GPRS. Seems to be enough to overcome the race scenario. - Using Arduino Mega.
void loop() {
ReadmyGPRS();
delay(10); //A race condition exists to get the data.
}
void ReadmyGPRS(){
if (Serial1.available()){ // if data is comming from GPRS serial port
count = 0; // reset counter
while(Serial1.available()) // reading data into char array
{
buffer[count++]=Serial1.read(); // writing data into array
if(count == 160)break;
}
Serial.write(buffer,count);
}
}

Arduino Serial Communication not receiving entire message

I have a problem with the Arduino communication. It's quite hard to describe so I cant fit it in the title. Anyway here are the following:
So I have this code for my receiving end:
if(Serial1.available())
{
while(Serial1.available())
{
uint8_t inByte = Serial1.read();
inByte = inByte ^ k;
Serial.write(inByte);
}
Serial.println(" done");
}
It's supposed to print in one line and print done when it's done. The Serial1.available() seems to skip the next Serial1.available(), I don't know what's going on. Anyway here's my current, bad, output:
h done
e done
l done
l done
o done
done
when it should be:
hello done
I'm sorry if this could've been phrased better but that's all I can type now, my brain is kinda in pain. I've never experienced this behavior in a Windows c++ console application.
If you are calling that routine in loop() then yes, it will read from the serial buffer and immediately return since you are probably not sending the data fast enough.
A better way to handle this sort of thing is to use a control char which indicates the end of a message OR if you have a specific data format you expect to receive, then keep a count of the chars which have come in until the data format limit is reached.
There is discussion here which you may find useful: Serial Duplex using Arduino Also there are example sketches that ship with the Arduino IDE: Menu: Examples: Communication:
Also, read all the entries under the Serial listing for Arduino. Good stuff there.
So the routine you develop for working with Serial input really depends on your project and the kind of data you are receiving. In your example above, if you were to use a control char, it might look like this:
while(Serial1.available()){
char c = Serial1.read();
if (c == '*'){
Serial.println(" done");
} else {
Serial.write(c);
}
}

Strange initial output using Serial.print

When I'm writing to the serial interface, I'm getting strange and unexpected output when my sketches first run. The output seems to be a variant of what should be printed:
eg:
String text1 = "foobar";
void setup() {
Serial.begin(9600);
Serial.print("\n");
Serial.print(text1);
}
void loop() {
}
Results in the output:
fo
foobar
(the new line appears before "fo" but I couldn't work out how to include it).
So some variant of whatever is supposed to be printed, gets printed before the actual text that is supposed to be printed. Changing the output, changes the anomalous text (sometimes it'll be two characters, sometimes three). Making changes that don't affect the output and recompiling has no effect on the anomalous text.
I'm a total Arduino newbie (I only started writing my own code today), but I can only assume this isn't normal.
I'm using a Freetronics EtherTen and the 1.0 IDE
thanks in advance
Arduino is restarting your sketch when you open its serial port on the computer.
so it prints out, and then initialized again.
after
Serial.begin(9600);
try to put either:
delay(500)
or
while (!Serial); // while the serial stream is not open, do nothing:
This is most likely a Serial communication Reset issue as Eran W pointed out. See my previous answer here.
The Arduino automatically resets when it receives serial communication from most things other than the Arduino IDE. This is why you can send from the IDE but not anything else.
I have an Uno and put a capacitor between Reset and Ground.Here's a page with some good info on the subject.
Good luck. http://arduino.cc/playground/Main/DisablingAutoResetOnSerialConnection
You should probably terminate your string with a 0.
Like:
String text1 = "foobar",0;

pySerial writes to Arduino Uno get buffered

I have a Python script that writes short messages to the serial port on my Arduino Uno board using pySerial. There is a loop and depending on some conditions, multiple writes can happen within a loop, something like this:
while True:
#Conditions block 1
if <CONDITION1>:
serial.writelines("INIT")
elif <CONDITION2>:
serial.writelines("NEW")
...
#Conditions block 2
if <CONDITION1>:
# Fetch something from the Internet
serial.writelines("CHECK")
elif <CONDITION2>:
# Fetch something from the Internet
serial.writelines("STOP")
...
But, when my Arduino board receives this it receives the first message as INIT, but the second one is being read as INITSTOP or INITCHECK and third one gets concatenated to the previous messages. My arduino program checks for specific message in this way:
if(msg.equals("CHECK")) {
// Do something
}
else if(msg.equals("INIT")) {
// Do Something else
}
Can anyone guide me on this? BTW, I don't think the problem is with the Arduino as it works perfectly when I test it with the Serial Monitor available with the IDE.
I've tried adding sleeps of upto 10 seconds before every write, but that did not work out.
Try this this instead:
serial.write("INIT\r")
The writelines probably takes a list (but I can't check it now).

Resources