[WORKING]Get Caller ID Electron -> enable Interrupt on PB12 aka RI_UC

Hey everybody,

#working code / answer:

#original thoughts:
I want to get the CallerID when somebody calls my electron. I definitly need a different Sim card for this, thats for sure.

The AT Command I need for that is:
AT+UCALLSTAT
which needs to be enabled (I do not know the default setting)

when a call occurs that it is giving me back the caller ID in this format:
+UCALLSTAT: <call_id>,<stat>

So far so good.

Now I want to determine what would be the best option for recognizing a call.
In another Thread they spoke about the PB12 pin which is connected to the “alert” pin (or so) of the ublox which I guess should trigger when a SMS or Call is coming in.
PD12 is not brought out to the standard D/A Pins. So I can’t set an Interrupt on them using the normal firmware (or can I?)

#what I need:

how to enable the Interrupt on PB12 on an Electron.

Or is anyone else thinking polling the Serial line is a better solution?
I might need that anyways because the +UCALLSTAT might occur earlier that the ISP…

Thanks for your help!

Project Idea: check if phone number is inside a local(/online) “database” and only if yes then toggle a relay. If not maybe send him a SMS for further instructions.

#EDIT:
The Datasheet says that the STM32 is supporting up to 140 interrupt able pins… So the chances are good…
Edit 2: the alternate Function name of this pin is TIM1_BKIN Timer 1… BK(?)Input sounds good…

EDIT3:
from reference manual:

6.3.8 External interrupt/wakeup lines

All ports have external interrupt capability. To use external interrupt lines, the port must be configured in input mode, refer to Section 8.2: External interrupt/event controller (EXTI) and Section 8.2.3: Wakeup event management.

EDIT4:

So I need to ORRS [0, =0x14] , =0x1 <-- that’s Assembler… and how to do this with C…? :smiley:

3 Likes
1 Like

thanks! yeah that helped a bit for the Method of doing it but not in general for the interrupt initialization. In there example code they were using an interrupt too. Or atleast an Interrupt pin but I saw no direct ISR or something like that…

The more interesting part was in there FONA.cpp file, especially this part:

boolean Adafruit_FONA::incomingCallNumber(char* phonenum) {
//+CLIP: “”,145,"",0,"",0
if(!Adafruit_FONA::_incomingCall)
return false;

readline();
while(!prog_char_strcmp(replybuffer, (prog_char*)F(“RING”)) == 0) {
flushInput();
readline();
}

readline(); //reads incoming phone number line

parseReply(F("+CLIP: “”), phonenum, ‘"’);

DEBUG_PRINT(F("Phone Number: "));
DEBUG_PRINTLN(replybuffer);

Adafruit_FONA::_incomingCall = false;
return true;
}

But the SIM800 is a different CHIPset and uses other AT commands… anyway thank you for your interest! :smile:

@harrisonhjones can you or any other engineer at Particle help me out setting up this custom Interrupt outside the standard brought-out-pins? :stuck_out_tongue:

I’m just lacking the knowledge to manipulate the register I found out and where to find how I need to setup the ISR… Seeing the pin as Input is also missing but not such a big deal (GPIO control register I guess?)

This might help.
https://github.com/spark/firmware/blob/develop/hal/src/stm32f2xx/interrupts_hal.c

That’s the way the firmware does it.

That open source repo is a never ending source of insight for How-To questions.

3 Likes

there we go…

/* RI_UC - 38 */ { GPIOB, GPIO_Pin_12, GPIO_PinSource12, NONE, NONE, NULL, NONE, PIN_MODE_NONE, 0, 0 },

Pin is already sort of registered
Got it from https://github.com/spark/firmware/blob/develop/hal/src/stm32f2xx/pinmap_hal.c

So the Pin is called RI_UC (RING_UbloxCommunication maybe? :smiley: ) … anyway
this way I could check if the normal Interrupt function works :blush:

2 Likes

I checked now compile without problem :smile:

// EXAMPLE USAGE

void blink(void);
int ledPin = D1;
volatile int state = LOW;

void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(RI_UC, INPUT_PULLUP);
  attachInterrupt(RI_UC, blink, CHANGE);
}

void loop()
{
  digitalWrite(ledPin, state);
}

void blink()
{
  state = !state;
}
1 Like

@mrlowalowa Did you get this RI interrupt working with a different SIM?

I had no time today… But a different SIM is definitly needed because on the Particle you can’t get calls / SMS…

Maybe I have to look up a command that enables the RING? That’s not a big deal…

The bigger deal is to buffer the output of the ublox and look into it when the ISP is triggered…
I do not know any other way to use cellular.command() to get an output generated by the ublox itself and not by any other command… (maybe I can issue a AT+HELP or any other short AT+command and get the buffer with the other output… ? :smiley: )

EDIT: Here it is… :smiley:

@RWB and @developer_bt, I got the RI interrupt working. Whenever I call I get the interrupt is working.

3 Likes

Using the Particle Dev IDE it’s not familiar of a RI_UX pin… in build.particle.io everything works…

The RI is getting triggered for call and SMS received. I am able to retrieve the incoming phone number during a call. Following is a sample code written for testing it. This code turn on the LED on D7 when an incoming call is received from predefined phone number. Note that you have to change the szPhone to your number.

When an incoming call is received then send the AT+CLCC command returns the list of current call. I am using AT+CPAS command to get phone activity state.This command will return a value from 0 to 5. The u-Blox AT Command Manual describes this command in detail.

One thing pending is to retrieve the incoming phone number when SMS is received. Any thoughts?

#define TIMEOUT 10000

void riInterrupt(void);

int ledPin = D7;
volatile int state = LOW;
char szIncomingPhone[16];
bool isCallRecognized = false;
bool isWaitingForCLCC = false;
char szPhone[] = "+919847237452";

int statusCallback(int type, const char* buf, int len, char* param){  
    Serial.print("Callback: ");
    Serial.write((const uint8_t*)&buf[2], len - 2);
    Serial.println();
    
    char szData[32];
    int status = -1;
    
    sscanf(&buf[2], "%s%d", szData, &status);

    if(strcmp(szData, "+CPAS:") == 0 && status == 0){
        state = LOW;
        
        szIncomingPhone[0] = '\0';
        isCallRecognized = false;
    }

    
    return WAIT;
}

int phoneCallback(int type, const char* buf, int len, char* param){  
    Serial.print("Callback: ");
    Serial.write((const uint8_t*)&buf[2], len - 2);
    Serial.println();
    
    char szData[32];
    int p1, p2, p3, p4, p5;
    int format;
    
    if(strncmp(&buf[2], "+CLCC", 5) == 0){
        sscanf(&buf[8], "%d, %d, %d, %d, %d, %[^/,]s, %d", &p1, &p2, &p3, &p4, &p5, szIncomingPhone, &format);
        
        strcpy(szIncomingPhone, &szIncomingPhone[1]);
    
        szIncomingPhone[strlen(szIncomingPhone) - 1] = 0;
        
        Serial.println(szIncomingPhone);
        Serial.println(szPhone);
        
        if(strcmp(szIncomingPhone, szPhone) == 0){
            Serial.println("Call detected");
            isCallRecognized = true;
            isWaitingForCLCC = false;
        }
        else{
            state = LOW;
            
            szIncomingPhone[0] = '\0';
            isCallRecognized = false;
        }
    }
    else if(isWaitingForCLCC && !isCallRecognized){
        state = LOW;
            
        szIncomingPhone[0] = '\0';
        isCallRecognized = false;    
        isWaitingForCLCC = false;
    }

    return WAIT;
}

void setup(){
    Serial.begin(115200);
    
    pinMode(ledPin, OUTPUT);
    pinMode(RI_UC, INPUT_PULLUP);
    
    attachInterrupt(RI_UC, riInterrupt, CHANGE);
}

void loop(){
    if(isCallRecognized)
        digitalWrite(ledPin, HIGH);
    else
        digitalWrite(ledPin, LOW);
    
    if(state == HIGH){
        char szReturn[32] = "";
        
        Serial.println("State is high");
        Serial.print("Phone Detected: ");
        Serial.println(isCallRecognized);
    
        if(strlen(szIncomingPhone) == 0){
            Serial.println("Detecting incoming phone number");
            
            isWaitingForCLCC = true;
            
            Cellular.command(phoneCallback, szReturn, TIMEOUT, "AT+CLCC\r\n");
        } else if(isCallRecognized == true){
            Serial.println("Getting status");
            
            isWaitingForCLCC = false;
            
            Cellular.command(statusCallback, szReturn, TIMEOUT, "AT+CPAS\r\n");
        }
    }
}

void riInterrupt(){
    state = digitalRead(RI_UC);
}
4 Likes

41:32: error: too few arguments to function 'int strncmp(const char*, const char*, size_t)'
Serial.print("Callback: ");

not really getting whats wrong here… :confused:

szData is not used but that’s just a warning…

and this here:

/usr/local/gcc-arm-embedded-gcc-arm-none-eabi-4_8-2014q2-20140609-linux-tar-bz2/arm-none-eabi/include/string.h:35:6: note: declared here
int _EXFUN(strncmp,(const char *, const char *, size_t));

It should be:

if(strncmp(&buf[2], "+CLCC", 5) == 0){

where 5 is equal to the string length of “+CLCC”. strncmp requires the number of characters that must be matched in order to return 0. This is different than strcmp which requires all of the characters in both strings match.

2 Likes

Correct @rickkas7, sorry, that was an unintentional issue after my experimentation to determine SMS. Corrected in the original post.

This strncmp can be avoided because the phoneCallback is only used for AT+CLCC command.

Thanks @rickkas7 for pointing out :smile:

@krvarma Great work on getting the Ring line working!

So can we use this to wake up the Electron from the sleeping modes?

1 Like

@krvarma I came across this code also for waking the Electron using the Ring line. Not sure if it’s helpful but I’ll post it anyway incase it is.

2 Likes

@RWB, I don’t think this can be used in deep sleep because it will shutdown the network system. But can be used in normal sleep because user code runs in that sleep. Not sure, need to experiment :smile:

1 Like

checkout this thread!

I found a finished test program on github for exactly this usage! :wink:
thanks to @technobly

@RWB looks like we found the same code… :smiley: in an commit they said that it would wake up the electron from sort of sleep. Also the current draw in this mode is mentioned(~18mA)!

4 Likes

@RWB, @mrlowalowa, looks like the code should work, wanted to play with it.

1 Like