Boron 3G/LTE Europe

Hello,

Tried out a 3G Boron here in Norway and it works great. I also got a Boron LTE unit which I am trying to get going as well with a SIM card from Telenor. CAT M1 is now available here in Norway, on channel 20 from what I can tell.

Big question; How can I make the Boron LTE module use the external sim card holder and register to the Telenor network here in Norway? The APN is ‘telenor.iot’ and I believe we use the 800/1800Mhz bands. Channel 20. My module is probably preconfigured for LTE in the US.

The regular setup process with the Boron LTE using the app seem to bail out after I say that I will not use the device as a mesh device.

I know this is not officially supported by Particle yet, but just interested in seeing what would it take to make this work. Any pointers are most welcome!

To set up a Boron with a 3rd-party SIM card you should follow the instructions here:

https://docs.particle.io/support/particle-devices-faq/electron-3rdparty-sims/

Note that is possible to set up a Boron LTE in other countries using a 3rd-party SIM card, but you’ll probably find it impossible to set up a mesh network because the mobile app setup does not support 3rd-party SIM cards and it’s not possible to set up a mesh network other than by the mobile app at this time.

2 Likes

@rickkas7 Awesome, that worked! Thanks for sharing. Boron LTE module seems to work well on the Telenor CAT M1 network here in Norway. Needed to specify a KeepAlive of 30 seconds though to make it keep the connection.

Hello :wave:t3:
Is it still not possible to setup a Mesh network with a LTE Boron out of the Americas?

Is the internal SIM going to support European countries anytime soon ? Norway, Switzerland and other countries do now have CAT-M1 networks as gularsen said.

Hello,

Would you please let me know how did you set-up the Boron LTE on the Telenor? I try to do it on Telia in Denmark by following the “set up a Boron with a 3rd-party SIM card” instruction but it doesn’t work!

This is the code I used to get the Boron LTE going with a Cat M1 sim from Telenor here in Norway:

/*
 * Project 3rdPartySIM
 * Description:
 * Author:
 * Date:
 */


#include "Particle.h"

#include "dct.h"

SYSTEM_MODE(SEMI_AUTOMATIC);

void setup() {
    Cellular.setActiveSim(EXTERNAL_SIM);
    Cellular.setCredentials("telenor.iot");

    // This clears the setup done flag on brand new devices so it won't stay in listening mode
    const uint8_t val = 0x01;
    dct_write_app_data(&val, DCT_SETUP_DONE_OFFSET, 1);

    // This is just so you know the operation is complete
    pinMode(D7, OUTPUT);
    digitalWrite(D7, HIGH);
}

void loop() {
}

Here is a modified Tinker app to go with it after the initial setup:

#include "Particle.h"

// Set your 3rd-party SIM APN here
// https://docs.particle.io/reference/firmware/electron/#setcredentials-
STARTUP(cellular_credentials_set("telenor.iot", "", "", NULL));
//STARTUP(cellular_credentials_set("telenor", "", "", NULL));

SerialLogHandler logHandler(LOG_LEVEL_ALL);

/* Function prototypes -------------------------------------------------------*/
int tinkerDigitalRead(String pin);
int tinkerDigitalWrite(String command);
int tinkerAnalogRead(String pin);
int tinkerAnalogWrite(String command);

SYSTEM_MODE(AUTOMATIC);

/* This function is called once at start up ----------------------------------*/
void setup()
{
	delay(5000);
	Serial.begin(115200);

	// Set the keep-alive value for 3rd party SIM card here
	// https://docs.particle.io/reference/firmware/electron/#particle-keepalive-
	Particle.keepAlive(30);

	//Setup the Tinker application here

	//Register all the Tinker functions
	Particle.function("digitalread", tinkerDigitalRead);
	Particle.function("digitalwrite", tinkerDigitalWrite);

	Particle.function("analogread", tinkerAnalogRead);
	Particle.function("analogwrite", tinkerAnalogWrite);
}

/* This function loops forever --------------------------------------------*/
void loop()
{
	//This will run in a loop
}

/*******************************************************************************
 * Function Name  : tinkerDigitalRead
 * Description    : Reads the digital value of a given pin
 * Input          : Pin
 * Output         : None.
 * Return         : Value of the pin (0 or 1) in INT type
                    Returns a negative number on failure
 *******************************************************************************/
int tinkerDigitalRead(String pin)
{
	//convert ascii to integer
	int pinNumber = pin.charAt(1) - '0';
	//Sanity check to see if the pin numbers are within limits
	if (pinNumber < 0 || pinNumber > 7) return -1;

	if(pin.startsWith("D"))
	{
		pinMode(pinNumber, INPUT_PULLDOWN);
		return digitalRead(pinNumber);
	}
	else if (pin.startsWith("A"))
	{
		pinMode(pinNumber+10, INPUT_PULLDOWN);
		return digitalRead(pinNumber+10);
	}
#if Wiring_Cellular
	else if (pin.startsWith("B"))
	{
		if (pinNumber > 5) return -3;
		pinMode(pinNumber+24, INPUT_PULLDOWN);
		return digitalRead(pinNumber+24);
	}
	else if (pin.startsWith("C"))
	{
		if (pinNumber > 5) return -4;
		pinMode(pinNumber+30, INPUT_PULLDOWN);
		return digitalRead(pinNumber+30);
	}
#endif
	return -2;
}

/*******************************************************************************
 * Function Name  : tinkerDigitalWrite
 * Description    : Sets the specified pin HIGH or LOW
 * Input          : Pin and value
 * Output         : None.
 * Return         : 1 on success and a negative number on failure
 *******************************************************************************/
int tinkerDigitalWrite(String command)
{
	bool value = 0;
	//convert ascii to integer
	int pinNumber = command.charAt(1) - '0';
	//Sanity check to see if the pin numbers are within limits
	if (pinNumber < 0 || pinNumber > 7) return -1;

	if(command.substring(3,7) == "HIGH") value = 1;
	else if(command.substring(3,6) == "LOW") value = 0;
	else return -2;

	if(command.startsWith("D"))
	{
		pinMode(pinNumber, OUTPUT);
		digitalWrite(pinNumber, value);
		return 1;
	}
	else if(command.startsWith("A"))
	{
		pinMode(pinNumber+10, OUTPUT);
		digitalWrite(pinNumber+10, value);
		return 1;
	}
#if Wiring_Cellular
	else if(command.startsWith("B"))
	{
		if (pinNumber > 5) return -4;
		pinMode(pinNumber+24, OUTPUT);
		digitalWrite(pinNumber+24, value);
		return 1;
	}
	else if(command.startsWith("C"))
	{
		if (pinNumber > 5) return -5;
		pinMode(pinNumber+30, OUTPUT);
		digitalWrite(pinNumber+30, value);
		return 1;
	}
#endif
else return -3;
}

/*******************************************************************************
 * Function Name  : tinkerAnalogRead
 * Description    : Reads the analog value of a pin
 * Input          : Pin
 * Output         : None.
 * Return         : Returns the analog value in INT type (0 to 4095)
                    Returns a negative number on failure
 *******************************************************************************/
int tinkerAnalogRead(String pin)
{
	//convert ascii to integer
	int pinNumber = pin.charAt(1) - '0';
	//Sanity check to see if the pin numbers are within limits
	if (pinNumber < 0 || pinNumber > 7) return -1;

	if(pin.startsWith("D"))
	{
		return -3;
	}
	else if (pin.startsWith("A"))
	{
		return analogRead(pinNumber+10);
	}
#if Wiring_Cellular
	else if (pin.startsWith("B"))
	{
		if (pinNumber < 2 || pinNumber > 5) return -3;
		return analogRead(pinNumber+24);
	}
#endif
	return -2;
}

/*******************************************************************************
 * Function Name  : tinkerAnalogWrite
 * Description    : Writes an analog value (PWM) to the specified pin
 * Input          : Pin and Value (0 to 255)
 * Output         : None.
 * Return         : 1 on success and a negative number on failure
 *******************************************************************************/
int tinkerAnalogWrite(String command)
{
	String value = command.substring(3);

	if(command.substring(0,2) == "TX")
	{
		pinMode(TX, OUTPUT);
		analogWrite(TX, value.toInt());
		return 1;
	}
	else if(command.substring(0,2) == "RX")
	{
		pinMode(RX, OUTPUT);
		analogWrite(RX, value.toInt());
		return 1;
	}

	//convert ascii to integer
	int pinNumber = command.charAt(1) - '0';
	//Sanity check to see if the pin numbers are within limits

	if (pinNumber < 0 || pinNumber > 7) return -1;

	if(command.startsWith("D"))
	{
		pinMode(pinNumber, OUTPUT);
		analogWrite(pinNumber, value.toInt());
		return 1;
	}
	else if(command.startsWith("A"))
	{
		pinMode(pinNumber+10, OUTPUT);
		analogWrite(pinNumber+10, value.toInt());
		return 1;
	}
	else if(command.substring(0,2) == "TX")
	{
		pinMode(TX, OUTPUT);
		analogWrite(TX, value.toInt());
		return 1;
	}
	else if(command.substring(0,2) == "RX")
	{
		pinMode(RX, OUTPUT);
		analogWrite(RX, value.toInt());
		return 1;
	}
#if Wiring_Cellular
	else if (command.startsWith("B"))
	{
		if (pinNumber > 3) return -3;
		pinMode(pinNumber+24, OUTPUT);
		analogWrite(pinNumber+24, value.toInt());
		return 1;
	}
	else if (command.startsWith("C"))
	{
		if (pinNumber < 4 || pinNumber > 5) return -4;
		pinMode(pinNumber+30, OUTPUT);
		analogWrite(pinNumber+30, value.toInt());
		return 1;
	}
#endif
else return -2;
}

Are you sure that your SIM supports LTE Cat M1?
This is not the same as LTE used on your mobile phone.

Thank you.
I did the same but it doesn’t work!
The problem might be related to the SIM. I will test another SIM …

I would expect that the SIM supports Cat-M1, but I am not sure!
Anyway, I will change it with another one …

Trying to get my first Boron LTE running here in Norway, with Telenor LTE-M/CAT-M1 external sim card.
But no luck :frowning:

I have set the external simcard, changed the credidentials to telenor.iot, but stuck on green blinking.
I checked the sim card status, and it is activated according to Telenor.
I am located in a central area with good coverage.

I tried the debug program, but i can’t really read/understand the results. Can anyone spot anything here?

starting tests...
turning cellular on...
0000015002 [system.nm] INFO: State changed: DISABLED -> IFACE_DOWN
0000020243 [hal] INFO: Using external Nano SIM card
deviceID=e00fce68462aa6ce1f02f52d
0000030335 [gsm0710muxer] INFO: Starting GSM07.10 muxer
0000030336 [gsm0710muxer] INFO: Openning mux channel 0
0000030336 [gsm0710muxer] INFO: GSM07.10 muxer thread started
0000030389 [gsm0710muxer] INFO: Resuming channel 0
0000030389 [gsm0710muxer] INFO: Openning mux channel 1
0000030441 [gsm0710muxer] INFO: Resuming channel 1
0000030441 [gsm0710muxer] INFO: Resuming channel 1
manufacturer=u-blox
model=SARA-R410M-02B
firmware version=L0.0.00.00.05.06 [Feb 03 2018 13:00:41]
ordering code=SARA-R410M-02B
IMEI=xxxxxxxxxxxx2267
IMSI=u-blox
ICCID=xxxxxxxxxxxxxx5568
0000030843 [app] INFO: enabling trace logging
0000030845 [ncp.at] TRACE: > AT+CGDCONT?
0000030893 [ncp.at] TRACE: < +CGDCONT: 1,"IP","telenor.iot","0.0.0.0",0,0,0,0
0000030894 [ncp.at] TRACE: < OK
0000030895 [ncp.at] TRACE: > AT+CSQ
0000030943 [ncp.at] TRACE: < +CSQ: 12,99
0000030943 [ncp.at] TRACE: < OK
attempting to connect to the cellular network...
0000030946 [system.nm] INFO: State changed: IFACE_DOWN -> IFACE_REQUEST_UP
0000030946 [system.nm] INFO: State changed: IFACE_DOWN -> IFACE_REQUEST_UP
0000030948 [hal] TRACE: PPP netif -> 8
0000030949 [net.ifapi] INFO: Netif pp3 state UP
0000030949 [net.ifapi] INFO: Netif pp3 state UP
0000030951 [hal] TRACE: PPP thread event LOWER_DOWN
0000030952 [hal] TRACE: PPP thread event ADM_DOWN
0000030954 [hal] TRACE: PPP thread event ADM_UP
0000030956 [hal] TRACE: State NONE -> READY
0000030955 [ncp.at] TRACE: > AT+CGDCONT=1,"IP","telenor.iot"
0000030958 [system.nm] INFO: State changed: IFACE_REQUEST_UP -> IFACE_UP
0000030958 [system.nm] INFO: State changed: IFACE_REQUEST_UP -> IFACE_UP
0000030993 [ncp.at] TRACE: < OK
0000030994 [ncp.at] TRACE: > AT+CEREG=2
0000031043 [ncp.at] TRACE: < OK
0000031043 [hal] TRACE: NCP connection state changed: 1
0000031044 [net.pppncp] TRACE: NCP event 2
0000031045 [net.pppncp] TRACE: State changed event: 1
0000031045 [hal] TRACE: PPP thread event LOWER_DOWN
0000031047 [ncp.at] TRACE: > AT+COPS=0,2
0000031093 [ncp.at] TRACE: < OK
0000031094 [ncp.at] TRACE: > AT+CEREG?
0000031143 [ncp.at] TRACE: < +CEREG: 2,2
0000031144 [ncp.at] TRACE: < OK
0000046244 [ncp.at] TRACE: > AT+CEREG?
0000046293 [ncp.at] TRACE: < +CEREG: 2,2
0000046293 [ncp.at] TRACE: < OK
0000061394 [ncp.at] TRACE: > AT+CEREG?
0000061443 [ncp.at] TRACE: < +CEREG: 2,2
0000061443 [ncp.at] TRACE: < OK
0000061631 [sys.power] TRACE: re-enabling charging
0000061673 [sys.power] TRACE: Battery state UNKNOWN -> CHARGED
0000062761 [sys.power] TRACE: Battery state CHARGED -> DISCONNECTED
0000076544 [ncp.at] TRACE: > AT+CEREG?
0000076593 [ncp.at] TRACE: < +CEREG: 2,2
0000076593 [ncp.at] TRACE: < OK
0000091694 [ncp.at] TRACE: > AT+CEREG?
0000091743 [ncp.at] TRACE: < +CEREG: 2,2
0000091743 [ncp.at] TRACE: < OK
0000106844 [ncp.at] TRACE: > AT+CEREG?
0000106893 [ncp.at] TRACE: < +CEREG: 2,2
0000106893 [ncp.at] TRACE: < OK
0000121994 [ncp.at] TRACE: > AT+CEREG?
0000122043 [ncp.at] TRACE: < +CEREG: 2,2
0000122043 [ncp.at] TRACE: < OK
0000122761 [sys.power] TRACE: re-enabling charging
0000122803 [sys.power] TRACE: Battery state UNKNOWN -> CHARGED
0000123891 [sys.power] TRACE: Battery state CHARGED -> DISCONNECTED
0000137144 [ncp.at] TRACE: > AT+CEREG?
0000137193 [ncp.at] TRACE: < +CEREG: 2,2
0000137193 [ncp.at] TRACE: < OK
0000152294 [ncp.at] TRACE: > AT+CEREG?
0000152343 [ncp.at] TRACE: < +CEREG: 2,2
0000152343 [ncp.at] TRACE: < OK
0000167444 [ncp.at] TRACE: > AT+CEREG?
0000167493 [ncp.at] TRACE: < +CEREG: 2,2
0000167493 [ncp.at] TRACE: < OK
0000182594 [ncp.at] TRACE: > AT+CEREG?
0000182643 [ncp.at] TRACE: < +CEREG: 2,2
0000182643 [ncp.at] TRACE: < OK
0000183891 [sys.power] TRACE: re-enabling charging
0000183933 [sys.power] TRACE: Battery state UNKNOWN -> CHARGED
0000185020 [sys.power] TRACE: Battery state CHARGED -> DISCONNECTED
0000197744 [ncp.at] TRACE: > AT+CEREG?
0000197797 [ncp.at] TRACE: < +CEREG: 2,2
0000197797 [ncp.at] TRACE: < OK

Thomlov: Did you ever get it to connect? I’m having the same issue…

Looking at the possible return codes from the AT+CREG? command :

0000031094 [ncp.at] TRACE: > AT+CEREG?
0000031143 [ncp.at] TRACE: < +CEREG: 2,2
0000031144 [ncp.at] TRACE: < OK

Possible values of registration status are,
0 not registered, MT is not currently searching a new operator to register to
1 registered, home network
2 not registered, but MT is currently searching a new operator to register to
3 registration denied
4 unknown (e.g. out of GERAN/UTRAN/E-UTRAN coverage)
5 registered, roaming
6 registered for "SMS only", home network (applicable only when indicates E-UTRAN)
7 registered for "SMS only", roaming (applicable only when indicates E-UTRAN)
8 attached for emergency bearer services only (see NOTE 2) (not applicable)
9 registered for "CSFB not preferred", home network (applicable only when indicates E-UTRAN)
10 registered for "CSFB not preferred", roaming (applicable only when indicates E-UTRAN)

Possible values for access technology are,
0 GSM
1 GSM Compact
2 UTRAN
3 GSM w/EGPRS
4 UTRAN w/HSDPA
5 UTRAN w/HSUPA
6 UTRAN w/HSDPA and HSUPA
7 E-UTRAN

It seems that the sim cannot register and that the transport is UTRAN - this means it is a 3G variant and not LTE - so this sim should work in a 3G Boron but will not work in an LTE one...

May want to check the MNO setting on the modem as well, if your SIM is ok. Particle seems to set this to something that works well in the US, but not in Europe. For Europe, it needs to be set to 100, per UBLOX’s AT Command document.

Thanks for sharing. What is your experience using the Boron LTE with a Telenor sim in Norway. Is it it stable, stays connected?

Have been working with the Boron 2/3G and it is very hard to connect to the network and often drops out, even when I use a large external antenna.

Hello,

I presume you use the Particle cloud. Cat M1 rollout in Norway is still ongoing, so you may want to check the coverage maps to see the status in the area of interest. I have tested quite a bit in Oslo, Bergen and Trondheim and the networks of Telenor and Telia both seem to work well.
Telenor seems to be further along than Telia with their rollout and shutdown of the 3G network.

My experiences are more on using Electron LTE, but we have done some tests on Boron LTE as well. Both seem to work well once you work through the initial issues.

Some things to keep in mind:

  1. Make sure the MNO is set to 100. Factory default is 0, deviceOS will force this to 1 if it sees the 0.
  2. Make sure the RAT is only set to 7. I think the deviceOS will do this for you.
  3. Depending on how your APN and SIM card is set up, the keepAlive value may vary a lot. We use a private APN in our deployments so this value can be somewhat configured. We use 18 minutes for our own SIM cards, but I did encounter one SIM from Telenor where I had to set it to 30 seconds to not lose my UDP backchannel NAT from the Particle server and to the device. I have used trial and error in the past to find a good value. This project may help you to find a correct keepAlive value: https://github.com/mstan/keep-alive-tester
  4. PSM and EDRX functionality are not really supported and are turned off by the deviceOS. The current consumption of the R410M modem is pretty awful without the use of these technologies, so we ended up instead of being online all the time, to wake up on a schedule and on actionable events. The reconnect time on CatM1 is pretty good.

0.02.

1 Like

Thanks a lot for the comprehensive reply and good advice! It is very much appreciated! We will try out Boron LTE next week.

We have managed to flash the Boron offline but it does noe connect to the cellular network, keep blinking green. We suspect this might be because of the MNO setting might be wrong. Would you be so kind to provide some advice on how we can change the MNO to 100?

Hello again,

I presume you want to use your own SIM?

  1. Make sure you specify this in your code per
    https://community.particle.io/t/setting-up-a-boron-with-a-3rd-party-sim-card/45226

  2. I created a sample app to help with MNO management for Electron, it should work for Boron too once you specify the usage of the external SIM.
    https://github.com/beachviking/particle-electron-r410m-toolbox

My application allows you to go through the connection process step by step. To change MNO, run the application. Then do a modemreg command(this turns on the modem). Then you should check/set MNO as needed. I have included a method which automates this, which you can run right after the modemreg command.

Hope this helps.

I recently tested Boron LTE in Sweden with 3rd-party SIM from Telenor and it works.

When I started it just flashed green all the time and every time I tried to set MVNO to 100 ( Europe) I get an error.

Then I noticed that firmware on onboard SARA R410 modem was to old ( from 2019) and understood modem firmware was the problem.

So I find this thread https://community.particle.io/t/ublox-modem-firmware-update/50205 but instead of using proposed programmer I soldered an USB cable to modem test pads on PCB.

Then I asked Ublox for newer firmware. After some discussion Ublox send me latest firmware, so I upgraded firmware and then I was able to set MVNO to 100.

See also https://forum.arduino.cc/t/firmware-upgrade-for-ublox-sara-r410m-02b-on-the-mkr-nb-1500-2/699292

1 Like