Big STM32 boards topic

@bluejedi Shall i doublepost to that forum?

In the meanwhile this is what i get from the OTAA example, with DEBUG set to 2:

`

Starting
RXMODE_RSSI
149062: engineUpdate, opmode=0x8
149248: Scheduled job 0x20000ab0, cb 0x8002f0f ASAP
Packet queued
156344: Running job 0x20000ab0, cb 0x8002f0f, deadline 0
156662
:
EV_JOINING
177014: engineUpdate, opmode=0xc
177198: Uplink join pending
177354: Airtime available at 297137 (previously determined)
177686: Uplink delayed until 297137
177887: Scheduled job 0x20000ab0, cb 0x8002f19 at 297012
297012: Running job 0x20000ab0, cb 0x8002f19, deadline 297012
297356: engineUpdate, opmode=0xc
297540: Uplink join pending
297696: Airtime available at 297137 (previously determined)
298029: Ready for uplink
298212: Updating info for TX at 297540, airtime will be 3856. Setting available time for band 0 to 4153540
298983: TXMODE, freq=433175000, len=23, SF=7, BW=125, CR=4/5, IH=0

`

I will have to merge some upstream changes but my repo should compile:

Note that the upstream repository is also different: https://github.com/rogerclarkmelbourne/Arduino_STM32
from the one you are using.

You should show the compile errors and link to your sources otherwise it is hard to help you.

1 Like

@tomtor Thanks for responding.

With your library arduino-LMIC (GitHub - tomtor/arduino-lmic: LoraWAN-in-C library, adapted to run under the Arduino environment) with the stmduino core (this one: GitHub - stm32duino/Arduino_Core_STM32: STM32 core support for Arduino) without any modifications, running the abp or otaa example from examples menu, i get the following output:
S
If i set

#define LMIC_DEBUG_LEVEL 2

in src>lmic>config.h
i get the following output:

Starting
RXMODE_RSSI
482261: irq: dio: 0x2 flags: 0x0
482470: Scheduled job 0x20000aa4, cb 0 ASAP
482725: Cleared job 0x20000aa4
482918: engineUpdate, opmode=0x8
483105: Scheduled job 0x20000aa4, cb 0x80019b3 ASAP
Packet queued
588697: irq: dio: 0x2 flags: 0x0
588907: Scheduled job 0x20000aa4, cb 0x80019b3 ASAP
589196: Running job 0x20000aa4, cb 0x80019b3, deadline 0
589513
:
EV_JOINING
905338: engineUpdate, opmode=0xc
905523: Uplink join pending
905678: Airtime available at 669098 (previously determined)
906010: Ready for uplink
906204: Updating info for TX at 905523, airtime will be 3856. Setting available time for band 0 to 4761523
906912: TXMODE, freq=868300000, len=23, SF=7, BW=125, CR=4/5, IH=0
907288: Running job 0x20000aa4, cb 0x800111d, deadline 0
907606: Scheduled job 0x20000aa4, cb 0x8000f25 at 981569
908387: irq: dio: 0x2 flags: 0x0
908597: Cleared job 0x20000aa4
908770: Scheduled job 0x20000aa4, cb 0x8000f25 ASAP
909060: Running job 0x20000aa4, cb 0x8000f25, deadline 0
FAILURE
C:\Users\XYZ\Documents\Arduino\libraries\arduino-lmic-master\src\lmic\radio.c:660

then it just stops doing nothing.

With the roger clark core it shows:

Starting
then nothing

With this core:

i get the following:

Starting
RXMODE_RSSI
482370: engineUpdate, opmode=0x8
482557: Scheduled job 0x20000aa4, cb 0x80019b3 ASAP
Packet queued
588149: irq: dio: 0x2 flags: 0x0
588359: Scheduled job 0x20000aa4, cb 0x80019b3 ASAP
588648: Running job 0x20000aa4, cb 0x80019b3, deadline 0
588966
:
EV_JOINING
904791: engineUpdate, opmode=0xc
904975: Uplink join pending
905131: Airtime available at 654022 (previously determined)
905463: Ready for uplink
905656: Updating info for TX at 904975, airtime will be 3856. Setting available time for band 0 to 4760975
906365: TXMODE, freq=868100000, len=23, SF=7, BW=125, CR=4/5, IH=0
906740: Running job 0x20000aa4, cb 0x800111d, deadline 0
907059: irq: dio: 0x2 flags: 0x0
907269: Scheduled job 0x20000aa4, cb 0x800111d ASAP
907558: Scheduled job 0x20000aa4, cb 0x8000f25 at 966493
907876: Running job 0x20000aa4, cb 0x8000f25, deadline 0
FAILURE
C:\Users\XYZ\Documents\Arduino\libraries\arduino-lmic-master\src\lmic\radio.c:660

then nothing.

And if i remove the comments lines from disableinterrupts, it just does nothing after showing

Starting

Now, if i comment out the assert line in radio.c line 660 and remove disableinterrupts line, it runs without giving an error. packets are now visible in ttn application. but i think it still canā€™t receive downstream messages:

Starting
Packet queued
549269
:
EV_JOINING
905114: engineUpdate, opmode=0xc
905298: Uplink join pending
905453: Airtime available at 608039 (previously determined)
905786: Ready for uplink
905978: Updating info for TX at 905297, airtime will be 3856. Setting available time for band 0 to 4761297
906742: TXMODE, freq=433175000, len=23, SF=7, BW=125, CR=4/5, IH=0

@tomtor Iā€™ve installed roger clark core (i am proceeding step by step) With your sketch in the solar example with deep sleep, it compiles.

  • Serial.print doesnā€™t give me anything. i replaced it with Serial1 then iā€™ve some thing on my usb->serial which i monitor using putty.

  • I get many extraneous characters on my putty. is it due to interference? SPI@1MHZ or the LORWAN radio@433mhz

  • If i comment out //#define SLEEP, it complains :
    'mdelay' was not declared in this scope

  • I want to add an OLED (ssd 1366 128x64 i2c) using adafruit library. i replaced all Serial.println() with msgOLED() defined below:

    void msgOLED(String s)
    {
    Serial1.println(s);

    if(lines++>10){
      display.clearDisplay();
      display.setCursor(0,0);
      display.setTextSize(1);
      display.setTextColor(WHITE);
      lines=0;
    }
    display.println(s);
    display.display();
    

    }
    void msgOLED(int s)
    {
    char temp[20];itoa(s,temp,10);
    Serial1.println(temp);

    if(lines++>10){
      display.clearDisplay();
      display.setCursor(0,0);
      display.setTextSize(1);
      display.setTextColor(WHITE);
      lines=0;
    }
    display.println(temp);
    display.display();
    

    }
    In the serial monitor i get:

    Enter do_seāø®
    2465

And then nothing. I donā€™t understand the sleep states properly, any help?

I think an oled would be a nice addition. this could be woken up by a GPIO pin or using a special downstream packet from the TTN consoleā€¦

@tomtor With the stm32duino core (not the roger clark one) these are my observations:

SPIClass mySPI(USE_SPI); gave errors, so i replaced it with SPI.begin() which gave the same problem of not doing anything after a call to osinit() is madeā€¦ Earlier i resolved the error by disabling everything relating to disabling interrupts in hal.cpp:

#else
static uint8_t irqlevel = 0;

void hal_disableIRQs () {
 //   noInterrupts();
 //   irqlevel++;
}

void hal_enableIRQs () {
 //   if(--irqlevel == 0) {
  //      interrupts();

        // Instead of using proper interrupts (which are a bit tricky
        // and/or not available on all pins on AVR), just poll the pin
        // values. Since os_runloop disables and re-enables interrupts,
        // putting this here makes sure we check at least once every
        // loop.
        //
        // As an additional bonus, this prevents the can of worms that
        // we would otherwise get for running SPI transfers inside ISRs
//        hal_io_check();
//    }
}
#endif

Further, hal_io_check leads to hanging of the chipā€¦
void hal_sleep () {
// Not implemented
}

//#include <libmaple/pwr.h>
//#include <libmaple/scb.h>

//#include <RTClock.h>

Then there are several errors relating to INPUT_ANALOG:
469: error: ā€˜INPUT_ANALOGā€™ was not declared in this scope

   pinMode(PA0, INPUT_ANALOG);

                ^~~~~~~~~~~~

I replace INPUT_ANALOG to INPUT
Then adc_enable and adc_disable is not definedā€¦i commented out all these calls. adc_read not declared.
I commented out #define SLEEP replaced all the mdelay() with delay()

In addition, i also modified DEVEUI to get data from the TTN console as follows:

static const u1_t DEVEUI[8]={ 0x43, 0x35, 0x42, 0x32, 0x24, 0x45, 0x23, 0x25 }; // reversed 8 bytes of DevEUI registered with ttnctl
void os_getDevEui (u1_t* buf) {
  // use chip ID:
//  memcpy(buf, &STM32_ID[1], 8);
memcpy(buf,DEVEUI,8);
  // Make locally registered:
//  buf[0] = buf[0] & ~0x3 | 0x1;
}

Otherwise, data doesnā€™t get forwarded to the TTN application from TTN gatewayā€¦

Now, i am looking forward to add an OLED to display various messages. to save battery, this could be woken up by a gpio pin or from upstream TTN downlink messageā€¦I will post my results laterā€¦

Starting from your ino sketch, after my modifications, it looks something like this:

This is the output on the serial monitor:

Enter do_send
212
Packet queued
Leave do_send
Leave setup
Enter onEvent
EV_JOINING
Leave onEvent

Regarding the garbled serial output when using sleep modes.

When the chip enters sleep mode, also the serial output stops. So you should have a small delay after the last print and just before entering sleep mode, so that the output can be successfully transmitted before the sleep is entered.

Using deep sleep modes should really be the last step in your project if everything else is working fine.

@tomtor Thanks for responding. i donā€™t understand sleep modes properly especially so in the stm32 framework. further, it has been pointed out that in the ā€œofficialā€ stm32duino, there is a support for HAL (http://www.stm32duino.com/viewtopic.php?f=42&t=97 )

From the experiments i carried out above with both the cores (https://github.com/stm32duino/Arduino_Core_STM32 ) and ( https://github.com/rogerclarkmelbourne/Arduino_STM32 ) have problems of similar nature. my guess is, it is related to IRQ/interrupts/timing issues as the timing of the chip is managed by stm32.

All in all, major problem for me is:

While i can send data to TTN, it is done only once. so if i have to send data periodically, for example temperature, pressure, altitude data from bmp180, what can i do to achieve that?
my guess is that the node doesnā€™t move to the next state. this could be because i disturbed its flow using commentsā€¦

  • Iā€™ve somehow managed OLED to display each of the Serial.print() messages by replacing all the Serial.println & Serial.print with msgOLED() which then calls Serial.println & display.println (from Adafruit Library) The keypoint to note is that we have to reinitialise OLED everytime it has to display something, else nothing gets printed on the oled. perhaps, some GPIOā€™s gets messed up by the LMIC library
  • Sleep would be required, but i leave to some later time because i donā€™t know enough how LMIC works and how stm32/arduino worksā€¦but one thing iā€™m quite sure is that stm32 is ā€œtheā€ right choice for the sensor nodes. it is not that pricey yet has support for so many peripherals and works for quite low voltages. directly connected to a 18650 lipo, it worksā€¦with 2 oleds, a battery capacity monitor, a lora modem (aithinker ra02, based on sx1278), stm32f103 with default setup still works. i am experimenting with ni-cd 1.2x4ā€¦with solar probably should work without any human intervention
  • SPI frequency@10mhz, i think, i a bit too high especially if wiring with dupont wires and in external environment with i2c onā€¦
  • In my opinion, both the cores exhibit similar behaviour. apart from a few libraries here and thereā€¦real problematic is calling noInterrupts in hal.cpp by the LMIC library. hal_io_check(); also seems to be problematic. but i have not investigated enough.
  • default library supplied by arduino-lmic project (https://github.com/matthijskooijman/arduino-lmic ) 1.5-arduino-2 also exhibits similar behaviourā€¦i think they have merged your changesā€¦so i think that should be the starting point to avoid confusionā€¦but maybe sleep/low frequency operations@8mhz etc have not been includedā€¦

Any insights on how to get continuous data, say every 10 minutes with oled woken up by GPIO interrupts/upstream data?

and once again thanks for any helpā€¦

See https://github.com/tomtor/arduino-lmic/commit/52583ab4f2cb958fa0d220a8e0fadd39f121df89

I do not disable interrrupts.

@tomtor For the ā€œofficialā€ stm32 core, #ifdef ARDUINO_ARCH_STM32F1 doesnā€™t work as pointed out by fpiSTM32 http://www.stm32duino.com/viewtopic.php?f=48&t=3489&start=10#p43857
hal_io_check(); Add low power delay Ā· tomtor/arduino-lmic@52583ab Ā· GitHub is equally problematicā€¦

it is defined as below in arduino-lmic/src/hal/hal.cpp at 0859fcd71de91a54498b83df58bae382559140e5 Ā· tomtor/arduino-lmic Ā· GitHub as:

static void hal_io_check() {
    uint8_t i;
    for (i = 0; i < NUM_DIO; ++i) {
        if (lmic_pins.dio[i] == LMIC_UNUSED_PIN)
            continue;

        if (dio_states[i] != digitalRead(lmic_pins.dio[i])) {
            dio_states[i] = !dio_states[i];
            if (dio_states[i])
                radio_irq_handler(i);
        }
    }
}

radio_irq_handler is defined in arduino-lmic/src/lmic/radio.c at master Ā· tomtor/arduino-lmic Ā· GitHub as below:

void radio_irq_handler (u1_t dio) {
    ostime_t now = os_getTime();
    if( (readReg(RegOpMode) & OPMODE_LORA) != 0) { // LORA modem
        u1_t flags = readReg(LORARegIrqFlags);
#if LMIC_DEBUG_LEVEL > 1
        lmic_printf("%lu: irq: dio: 0x%x flags: 0x%x\n", now, dio, flags);
#endif
        if( flags & IRQ_LORA_TXDONE_MASK ) {
            // save exact tx time
            LMIC.txend = now - us2osticks(43); // TXDONE FIXUP
        } else if( flags & IRQ_LORA_RXDONE_MASK ) {
            // save exact rx time
            if(getBw(LMIC.rps) == BW125) {
                now -= TABLE_GET_U2(LORA_RXDONE_FIXUP, getSf(LMIC.rps));
            }
            LMIC.rxtime = now;
            // read the PDU and inform the MAC that we received something
            LMIC.dataLen = (readReg(LORARegModemConfig1) & SX1272_MC1_IMPLICIT_HEADER_MODE_ON) ?
                readReg(LORARegPayloadLength) : readReg(LORARegRxNbBytes);
            // set FIFO read address pointer
            writeReg(LORARegFifoAddrPtr, readReg(LORARegFifoRxCurrentAddr));
            // now read the FIFO
            readBuf(RegFifo, LMIC.frame, LMIC.dataLen);
            // read rx quality parameters
            LMIC.snr  = readReg(LORARegPktSnrValue); // SNR [dB] * 4
            LMIC.rssi = readReg(LORARegPktRssiValue) - 125 + 64; // RSSI [dBm] (-196...+63)
        } else if( flags & IRQ_LORA_RXTOUT_MASK ) {
            // indicate timeout
            LMIC.dataLen = 0;
        }
        // mask all radio IRQs
        writeReg(LORARegIrqFlagsMask, 0xFF);
        // clear radio IRQ flags
        writeReg(LORARegIrqFlags, 0xFF);
    } else { // FSK modem
        u1_t flags1 = readReg(FSKRegIrqFlags1);
        u1_t flags2 = readReg(FSKRegIrqFlags2);
        if( flags2 & IRQ_FSK2_PACKETSENT_MASK ) {
            // save exact tx time
            LMIC.txend = now;
        } else if( flags2 & IRQ_FSK2_PAYLOADREADY_MASK ) {
            // save exact rx time
            LMIC.rxtime = now;
            // read the PDU and inform the MAC that we received something
            LMIC.dataLen = readReg(FSKRegPayloadLength);
            // now read the FIFO
            readBuf(RegFifo, LMIC.frame, LMIC.dataLen);
            // read rx quality parameters
            LMIC.snr  = 0; // determine snr
            LMIC.rssi = 0; // determine rssi
        } else if( flags1 & IRQ_FSK1_TIMEOUT_MASK ) {
            // indicate timeout
            LMIC.dataLen = 0;
        } else {
            ASSERT(0);
        }
    }
    // go from stanby to sleep
    opmode(OPMODE_SLEEP);
    // run os job (use preset func ptr)
    os_setCallback(&LMIC.osjob, LMIC.osjob.func);
}

Serial.flush()

It is better to use Serial.flush() instead of using delay() before entering sleep.

Serial.flush() waits for the transmission of outgoing serial data to complete.
delay() does not know when and if the serial transmission has completed so you have to use a safety margin for the delay value. This will cause that the delay takes longer than required.
Serial.flush() is both more reliable and more efficient. It guarantees that all serial data has transmitted and prevents unnecessary delays. Delays that use more power because they delay entering the sleep state.

Unnecessary delay is the time between completion of the serial transmission and completion of delay().

@bluejedi i will try to replace all the mdelay() / delay() statements with Serial.flush() and report back laterā€¦right now i donā€™t have much timeā€¦besides i need to experiment a bit with stm32 timers/isr http://docs.leaflabs.com/static.leaflabs.com/pub/leaflabs/maple-docs/latest/timers.html using the stm32duino core

iā€™ve somehow managed to send data to TTN. it is shown in ttn applications>data section with proper variables with ABP. OTAA still doesnā€™t workā€¦callback works properly now in ABP i can see TX_COMPLETE event. this is with the ā€œofficialā€ stm32core which supports stm32 halā€¦https://github.com/stm32duino/Arduino_Core_STM32

In the current form the sketch looks like this: https://github.com/iotlearner0level/TTN-OLED-SENSORNODE-STM32/blob/master/v3oled.ino
lora modem (sx1278 based aithinker ra02) is connected to SPI1 an OLED ssd1306 is connected to i2c1 (pa6/7) bmp180 is connected to pa10/11 it takes power from gpio pins (low power device, so it should be ok) iā€™ve redefined bmp180.h and bmp180.c to used twowire on those two pins for the bmp. rest of the sketch is based on tomtorā€™s solar example but iā€™ve removed all the sleep statements. apparently, sleep in the official core works a bit different.

The keypoint was that we have to disable in the libraries nointerrupts and disablehal and it seems to work ok.

now i want two additional features:

  • I am testing various batteries (nimhx4, nicdx4, 1-18650 connected to Vin pin, 2x18650 lipo connected to Vin) so i also need to send Vcc voltage. How to get Vcc in stm32. method prescribed in original sketch doesnā€™t seem to workā€¦
  • SLEEP Mode, which seem to work differently in the official core

thanks

I am using this code to read the voltage without an external voltage divider:

int readVInt()
{
  adc_enable(ADC1);

  adc_reg_map *regs = ADC1->regs;
  regs->CR2 |= ADC_CR2_TSVREFE; // enable VREFINT and temp sensor
  regs->SMPR1 = (ADC_SMPR1_SMP17); // sample rate for VREFINT ADC channel

  int vref = 1210 * 4096 / adc_read(ADC1, 17); // ADC sample to millivolts
  regs->CR2 &= ~ADC_CR2_TSVREFE; // disable VREFINT and temp sensor
  return vref;
}

This gives compiler error for the hal enabled core at GitHub - stm32duino/Arduino_Core_STM32: STM32 core support for Arduino :
C:\Users\XYZ\Documents\Arduino\stm32\sketch_apr23a\sketch_apr23a.ino: In function ā€˜int readVInt()ā€™:

sketch_apr23a:12: error: 'adc_enable' was not declared in this scope

   adc_enable(ADC1);

                  ^

sketch_apr23a:14: error: 'adc_reg_map' was not declared in this scope

   adc_reg_map *regs = ADC1->regs;

   ^~~~~~~~~~~

sketch_apr23a:14: error: 'regs' was not declared in this scope

   adc_reg_map *regs = ADC1->regs;

                ^~~~

sketch_apr23a:14: error: 'struct ADC_TypeDef' has no member named 'regs'

   adc_reg_map *regs = ADC1->regs;

                             ^~~~

sketch_apr23a:18: error: 'adc_read' was not declared in this scope

   int vref = 1210 * 4096 / adc_read(ADC1, 17); // ADC sample to millivolts

                                             ^

exit status 1
'adc_enable' was not declared in this scope

after some google search, hal adc for bluepill stm32f103 boards are defined here:

I canā€™t make much ot of it right now. maybe iā€™ve to spend lots of time to figure out how that works.

Just in case anyone is interested in the ā€œofficialā€ stm32 core GitHub - stm32duino/Arduino_Core_STM32: STM32 core support for Arduino

Based on fpiSTMā€™s suggestion from the stm32duino forums, we can read chip voltage & temperature using the following:

uint16_t adc_read(uint32_t channel)
{
  ADC_HandleTypeDef AdcHandle = {};
  ADC_ChannelConfTypeDef  AdcChannelConf = {};
  __IO uint16_t uhADCxConvertedValue = 0;

  AdcHandle.Instance = ADC1;
  AdcHandle.State = HAL_ADC_STATE_RESET;
  AdcHandle.Init.DataAlign             = ADC_DATAALIGN_RIGHT;           /* Right-alignment for converted data */
  AdcHandle.Init.ScanConvMode          = DISABLE;                       /* Sequencer disabled (ADC conversion on only 1 channel: channel set on rank 1) */
  AdcHandle.Init.ContinuousConvMode    = DISABLE;                       /* Continuous mode disabled to have only 1 conversion at each conversion trig */
  AdcHandle.Init.DiscontinuousConvMode = DISABLE;                       /* Parameter discarded because sequencer is disabled */
  AdcHandle.Init.ExternalTrigConv      = ADC_SOFTWARE_START;            /* Software start to trig the 1st conversion manually, without external event */
  AdcHandle.Init.NbrOfConversion       = 1;                             /* Specifies the number of ranks that will be converted within the regular group sequencer. */
  AdcHandle.Init.NbrOfDiscConversion   = 0;                             /* Parameter discarded because sequencer is disabled */

  if (HAL_ADC_Init(&AdcHandle) != HAL_OK) {
    return 0;
  }

  AdcChannelConf.Channel      = channel;             /* Specifies the channel to configure into ADC */
  AdcChannelConf.Rank         = ADC_REGULAR_RANK_1;               /* Specifies the rank in the regular group sequencer */
  AdcChannelConf.SamplingTime = ADC_SAMPLETIME_13CYCLES_5;                     /* Sampling time value to be set for the selected channel */

  /*##-2- Configure ADC regular channel ######################################*/
  if (HAL_ADC_ConfigChannel(&AdcHandle, &AdcChannelConf) != HAL_OK)
  {
    /* Channel Configuration Error */
    return 0;
  }
  /*##-2.1- Calibrate ADC then Start the conversion process ####################*/
  if (HAL_ADCEx_Calibration_Start(&AdcHandle) !=  HAL_OK) {
    /* ADC Calibration Error */
    return 0;
  }
  /*##-3- Start the conversion process ####################*/
  if (HAL_ADC_Start(&AdcHandle) != HAL_OK) {
    /* Start Conversation Error */
    return 0;
  }
  /*##-4- Wait for the end of conversion #####################################*/
  /*  For simplicity reasons, this example is just waiting till the end of the
      conversion, but application may perform other tasks while conversion
      operation is ongoing. */
  if (HAL_ADC_PollForConversion(&AdcHandle, 10) != HAL_OK) {
    /* End Of Conversion flag not set on time */
    return 0;
  }
  /* Check if the continous conversion of regular channel is finished */
  if ((HAL_ADC_GetState(&AdcHandle) & HAL_ADC_STATE_REG_EOC) == HAL_ADC_STATE_REG_EOC) {
    /*##-5- Get the converted value of regular channel  ########################*/
    uhADCxConvertedValue = HAL_ADC_GetValue(&AdcHandle);
  }

  if (HAL_ADC_Stop(&AdcHandle) != HAL_OK) {
    /* Stop Conversation Error */
    return 0;
  }
  if(HAL_ADC_DeInit(&AdcHandle) != HAL_OK) {
    return 0;
  }
  return uhADCxConvertedValue;
}

void setup() {
  Serial.begin(115000);
  analogRead(A0); // Workaround to init g_current_pin used in HAL_ADC_MspInit
}

void loop() {
  float Vdd = readVdd();
  Serial.print("Vdd=  ");
  Serial.print(Vdd);
  Serial.print(" V Temp= ");
  Serial.print(readTempSensor(Vdd));
  Serial.println(" Ā°C");
  delay(500);
}

static float readVdd()
{
  return (1.20 * 4096.0 / adc_read(ADC_CHANNEL_VREFINT)); // ADC sample to V
  //return (1200 * 4096 / adc_read(ADC_CHANNEL_VREFINT)); // ADC sample to mV
}

static float readTempSensor(float Vdd)
{
  return ((1.43 - (Vdd / 4096.0 * adc_read(ADC_CHANNEL_TEMPSENSOR))) / 0.0043 + 25.0);
}

Iā€™ve also updated my sketch which now sends bmp180 Pressure,temperature, altitude, chip temperature and Vdd. Vdd is especially helpful in battery operated scenarios.

sketch is here:

TTN-OLED-SENSORNODE-STM32/v4oled.ino at master Ā· iotlearner0level/TTN-OLED-SENSORNODE-STM32 Ā· GitHub

In addition, fpiSTM has indicated that sleep/low power API will be available soon, so it may be a matter of a few weeks or a month and we can use arduino library calls for low power without even using register stuff.

Just of reference, iā€™ve created a link to reading Vdd/chip temperature in official core just in case it is useful:

1 Like

Just in case anyone interested, bluepill boards seem to work upto 2.0V@72Mhz. Iā€™ve connected 4xNiMh to Vin (5V input) Fully charged it starts from 5.4V then keeps on droppingā€¦I get around 10hours with everything running (around 80mA, approx 50mA for the bluepill+lora and another 30mA for an electrical parameter tester)

From the voltage levels reported by chip, it seems it works ok upto 2.0V along with the lora radio (aithinker ra02/sx1278) without any special low frequency mode. bmp180 (connected to GPIO pins for Vcc/GND) also seem to work. last correct reading shows voltage of 2.67V (for the stm32). but the oled did not work that lowā€¦

here is o/p from the TTN storage integration console:

  {
    "altitude": 173,
    "chipTemp": 45.51,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 992,
    "raw": "DMYD4ACtCPcRxw==",
    "temperature": 32.7,
    "time": "2018-04-26T15:08:31.886672246Z",
    "voltage": 2.295
  },
  {
    "altitude": 173,
    "chipTemp": 49.07,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 992,
    "raw": "DMYD4ACtCJwTKw==",
    "temperature": 32.7,
    "time": "2018-04-26T15:09:43.815344082Z",
    "voltage": 2.204
  },
  {
    "altitude": 173,
    "chipTemp": 48.57,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 992,
    "raw": "DMYD4ACtCK8S+Q==",
    "temperature": 32.7,
    "time": "2018-04-26T15:09:48.870310385Z",
    "voltage": 2.223
  },
  {
    "altitude": 173,
    "chipTemp": 47.48,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 992,
    "raw": "DMYD4ACtCKwSjA==",
    "temperature": 32.7,
    "time": "2018-04-26T15:09:59.018495216Z",
    "voltage": 2.22
  },
  {
    "altitude": 173,
    "chipTemp": 48.14,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 992,
    "raw": "DMYD4ACtCKASzg==",
    "temperature": 32.7,
    "time": "2018-04-26T15:10:09.111891725Z",
    "voltage": 2.208
  },
  {
    "altitude": 172,
    "chipTemp": 47.36,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 992,
    "raw": "DMYD4ACsCL0SgA==",
    "temperature": 32.7,
    "time": "2018-04-26T15:10:14.443139847Z",
    "voltage": 2.237
  },
  {
    "altitude": 172,
    "chipTemp": 48.53,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 992,
    "raw": "DMYD4ACsCJYS9Q==",
    "temperature": 32.7,
    "time": "2018-04-26T15:10:21.023027081Z",
    "voltage": 2.198
  },
  {
    "altitude": 173,
    "chipTemp": 48.65,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 992,
    "raw": "DMYD4ACtCI0TAQ==",
    "temperature": 32.7,
    "time": "2018-04-26T15:10:27.35627427Z",
    "voltage": 2.189
  },
  {
    "altitude": 172,
    "chipTemp": 49.24,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 992,
    "raw": "DMYD4ACsCIYTPA==",
    "temperature": 32.7,
    "time": "2018-04-26T15:10:33.76306509Z",
    "voltage": 2.182
  },
  {
    "altitude": 173,
    "chipTemp": 48.93,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 992,
    "raw": "DMYD4ACtCIETHQ==",
    "temperature": 32.7,
    "time": "2018-04-26T15:10:39.810258704Z",
    "voltage": 2.177
  },
  {
    "altitude": 173,
    "chipTemp": 49.44,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 992,
    "raw": "DMYD4ACtCHcTUA==",
    "temperature": 32.7,
    "time": "2018-04-26T15:10:45.594316777Z",
    "voltage": 2.167
  },
  {
    "altitude": 112,
    "chipTemp": 50.59,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 999,
    "raw": "BQAD5wBwCGoTww==",
    "temperature": 12.8,
    "time": "2018-04-26T15:10:54.261388134Z",
    "voltage": 2.154
  },
  {
    "altitude": 112,
    "chipTemp": 50.82,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 999,
    "raw": "BQAD5wBwCFkT2g==",
    "temperature": 12.8,
    "time": "2018-04-26T15:11:02.42113182Z",
    "voltage": 2.137
  },
  {
    "altitude": 112,
    "chipTemp": 50.96,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 999,
    "raw": "BQAD5wBwCE0T6A==",
    "temperature": 12.8,
    "time": "2018-04-26T15:11:10.264988356Z",
    "voltage": 2.125
  },
  {
    "altitude": 112,
    "chipTemp": 51.08,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 999,
    "raw": "BQAD5wBwCEQT9A==",
    "temperature": 12.8,
    "time": "2018-04-26T15:11:17.896079546Z",
    "voltage": 2.116
  },
  {
    "altitude": 112,
    "chipTemp": 51.41,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 999,
    "raw": "BQAD5wBwCD0UFQ==",
    "temperature": 12.8,
    "time": "2018-04-26T15:11:25.272545344Z",
    "voltage": 2.109
  },
  {
    "altitude": 112,
    "chipTemp": 50.77,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 999,
    "raw": "BQAD5wBwCDgT1Q==",
    "temperature": 12.8,
    "time": "2018-04-26T15:11:32.674394192Z",
    "voltage": 2.104
  },
  {
    "altitude": 112,
    "chipTemp": 52,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 999,
    "raw": "BQAD5wBwCCIUUA==",
    "temperature": 12.8,
    "time": "2018-04-26T15:11:41.797026116Z",
    "voltage": 2.082
  },
  {
    "altitude": 172,
    "chipTemp": 52.94,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 992,
    "raw": "DMYD4ACsCA8Urg==",
    "temperature": 32.7,
    "time": "2018-04-26T15:11:47.370536356Z",
    "voltage": 2.063
  },
  {
    "altitude": 172,
    "chipTemp": 52.39,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 992,
    "raw": "DMYD4ACsCAwUdw==",
    "temperature": 32.7,
    "time": "2018-04-26T15:11:52.945451005Z",
    "voltage": 2.06
  },
  {
    "altitude": 172,
    "chipTemp": 52.48,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 992,
    "raw": "DMYD4ACsCAUUgA==",
    "temperature": 32.7,
    "time": "2018-04-26T15:11:58.259530726Z",
    "voltage": 2.053
  },
  {
    "altitude": 173,
    "chipTemp": 52.8,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 992,
    "raw": "DMYD4ACtB/8UoA==",
    "temperature": 32.7,
    "time": "2018-04-26T15:12:03.329723118Z",
    "voltage": 2.047
  },
  {
    "altitude": 172,
    "chipTemp": 52.65,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 992,
    "raw": "DMYD4ACsB/gUkQ==",
    "temperature": 32.7,
    "time": "2018-04-26T15:12:08.406844851Z",
    "voltage": 2.04
  },
  {
    "altitude": 172,
    "chipTemp": 53.55,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 992,
    "raw": "DMYD4ACsB/AU6w==",
    "temperature": 32.7,
    "time": "2018-04-26T15:12:13.211109286Z",
    "voltage": 2.032
  },
  {
    "altitude": 172,
    "chipTemp": 53.27,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 992,
    "raw": "DMYD4ACsB+sUzw==",
    "temperature": 32.7,
    "time": "2018-04-26T15:12:17.761658036Z",
    "voltage": 2.027
  },
  {
    "altitude": 172,
    "chipTemp": 54.03,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 992,
    "raw": "DMYD4ACsB+UVGw==",
    "temperature": 32.7,
    "time": "2018-04-26T15:12:22.332773405Z",
    "voltage": 2.021
  },
  {
    "altitude": 172,
    "chipTemp": 54.47,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 992,
    "raw": "DMYD4ACsB94VRw==",
    "temperature": 32.7,
    "time": "2018-04-26T15:12:26.623906536Z",
    "voltage": 2.014
  },
  {
    "altitude": 172,
    "chipTemp": 53.86,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 992,
    "raw": "DMYD4ACsB9cVCg==",
    "temperature": 32.7,
    "time": "2018-04-26T15:12:30.66988373Z",
    "voltage": 2.007
  },
  {
    "altitude": 172,
    "chipTemp": 54.36,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 992,
    "raw": "DMYD4ACsB9QVPA==",
    "temperature": 32.7,
    "time": "2018-04-26T15:12:34.728438098Z",
    "voltage": 2.004
  },
  {
    "altitude": 172,
    "chipTemp": 55.15,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 992,
    "raw": "DLsD4ACsB8oViw==",
    "temperature": 32.59,
    "time": "2018-04-26T15:12:43.351249396Z",
    "voltage": 1.994
  },
  {
    "altitude": 169,
    "chipTemp": 42.37,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 993,
    "raw": "DIkD4QCpDM4QjQ==",
    "temperature": 32.09,
    "time": "2018-04-26T15:48:49.328256588Z",
    "voltage": 3.278
  },
  {
    "altitude": 170,
    "chipTemp": 46.4,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 993,
    "raw": "DIkD4QCqDMESIA==",
    "temperature": 32.09,
    "time": "2018-04-26T15:50:02.785980618Z",
    "voltage": 3.265
  },
  {
    "altitude": 169,
    "chipTemp": 45.49,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 993,
    "raw": "DIkD4QCpDNMRxQ==",
    "temperature": 32.09,
    "time": "2018-04-26T15:51:17.9793614Z",
    "voltage": 3.283
  },
  {
    "altitude": 169,
    "chipTemp": 44.37,
    "device_id": "lora-gateway-node-ra01",
    "pressure": 992,
    "raw": "DJQD4ACpDNMRVQ==",
    "temperature": 32.2,
    "time": "2018-04-26T15:52:33.173748387Z",
    "voltage": 3.283
  },

Better leave some of it. :grin:

Problems with Arduino-LMIC and the offficial STM32 Arduino Core

I have seen this mentioned in several places but I cannot recall having seen it explained with a single good solution to fix it. I hope I just overlooked. :slightly_smiling_face:

I have some sketches that worked with the STM32F103C8T6 (128kb) ā€˜bluepillā€™ board + RFM95W when using Roger Clarks ā€˜stmduino coreā€™.
But when I try the same sketches with the official STM32 Arduino Core then the code somewhere fails (LMIC-Arduino related).

Can anyone explain why this happens and what is the best way to fix it.

With ā€˜best wayā€™ I mean, the most proper / most correct / most future proof / best maintainable / lowest impact / best craftsmanship way (if you get my point).

1 Like

to quote fpiSTM (official maintainer of the project)

STM core uses CMSIS so the way accessing registers is different.

Roger clark core is based on libmaple (GitHub - leaflabs/libmaple: [INACTIVE] C and C++ library for STM32 ARM Cortex-M3 development boards. and documentation: http://docs.leaflabs.com/docs.leaflabs.com/index.html )

I do not understand the internal details, so canā€™t go deeper. There is nothing futureproof, anything new breaks old :slight_smile: Hoever, any specific queries can be resolved by raising issues in the github for the official core or in stm32duino forum.

Yes, I was aware of that already, thanks.
But now Iā€™m looking for a good solution and try to avoid poorly maintainable custom hacks where possible.
I would prefer a wrapper / compatibility layer / abstraction-layer-like solution that hides away implementation differences from application code (and libraries). Which is why you would normally use a (Hardware) Abstraction Layer. And a HAL is exactly what the official STM32 Arduino Core is based on (a HAL that hides away implementation differences of different STM32 MCUā€™s).
In this case the STM32 Arduino Core introduces an incompatibility for LMIC-Arduino that Rogerā€™s stmduino core does not appear to suffer from. This is an incompatibility with Arduino (not an incompatibility with stm32duino core).

Having some STM supported automated conversion tool that can translate differences (where possible) would be great. Or at least have a compatibility scanner that can check existing Arduino code for possible conflict areas that need attention / require changes. That would be more preferable and much more productive than having to follow the ā€˜oops this doesnā€™t work, appears to be incompatible, now start looking where to fix thisā€™ manual approach for existing sketches and libraries.

My opinion is that it is better to use the official STM32 Arduino Core instead of the Maple based stm32duino core and try to get ironed out any issues and incompatibilities where possible.
Rogerā€™s older Maple based stm32duino is based on a fixed architecture from specific STM32 MCU model(s) and does not allow to be (easily) adapted for and provide support for newer STM32 MCUā€™s and is not supported by STM (STM32 Arduino Core is). So it is much less future proof. But I am unaware of what STMā€™s support for STM32 Arduino Core actually includes.