Unità MangOH Red

Descrizione del prodotto

L'unità mangOH™ Red è una piattaforma a basso consumo per Internet delle cose (IoT) in grado di funzionare a batteria fino a 10 anni. Secondo mangoh.io essa offre:

  • Fattore di forma pari a una carta di credito ideale per realizzare rapidamente dimostrazioni della validità dei progetti in fase di sviluppo;
  • Uno zoccolo a innesto per l'aggiunta di qualunque modulo compatibile con CF3™, compresi i moduli wireless (da 2G a 4G e LTE-M/NB-IoT), per ottenere una durata della batteria fino a 10 anni (per questo articolo è stato utilizzato un modulo CF3 WP8548_1103113 (codice componente DigiKey 1645-1022-1-ND));
  • Uno slot per schede di espansione IoT in cui inserire qualunque tecnologia basata sullo standard aperto di tali schede;
  • Una Smart SIM di Sierra Wireless integrata con dati gratuiti fino a un massimo di 100 MB, a seconda dell'area geografica, con la possibilità di utilizzare anche qualunque SIM disponibile in commercio;
  • L'integrazione con la piattaforma IoT AirVantage per creare, distribuire e gestire le soluzioni nel cloud;
  • Wi-Fi b/g/n e Bluetooth 4.2 BLE incorporati con un core Cortex-M4 per l'accesso in tempo reale agli I/O; e
  • Un accelerometro/giroscopio e sensori di pressione e di luce incorporati, oltre a un connettore a 26 pin compatibile con Raspberry Pi (il codice componente DigiKey del cavo per il connettore è 1597-1065-ND).

    (Immagine per gentile concessione di Talon Communications Inc.)

    Contenuto della confezione

    La confezione aperta per questo articolo conteneva:

    • Unità mangOH Red
    • Modulo CF3 (WP8548_1103113 nel nostro caso)
    • Cavo Micro-USB
    • 2 antenne (1 principale e 1 per il sistema satellitare di navigazione globale (GNSS)
    • Scheda micro SIM Sierra Wireless con allocazione iniziale dei dati

    Installazione hardware

    Seguire le istruzioni di installazione contenute nella Guida per l'installazione e l'uso dell'unità mangOH Red.

    Sull'unità mangOH Red sono presenti due porte Micro-USB.

    L'installazione hardware è risultata particolarmente semplice: è stato sufficiente collegare il cavo Micro-USB all'unità mangOH e a un computer, collegare le antenne e inserire la scheda SIM nello slot presente sul lato posteriore dell'unità mangOH. La figura riportata di seguito mostra un'illustrazione dell'architettura hardware tratta dalla Guida mangOH Red per gli sviluppatori:

    (Immagine per gentile concessione di Talon Communications Inc.)

    Connettore per Raspberry Pi.

    Il codice componente DigiKey del connettore per cavi a nastro è 1597-1065-ND. Le immagini riportate di seguito mostrano lo schema della piedinatura sia per il Raspberry Pi (nel quale i pin non utilizzati dall'unità MangOH Red sono ombreggiati), sia per l'unità MangOH Red: i collegamenti sono dal pin 1 al pin 1, dal pin 2 al pin 2 e così via.

    (Immagine per gentile concessione di pinout.xyz)

    (Immagine per gentile concessione di Talon Communications Inc.)

    Installazione software

    L'installazione software è risultata leggermente più complicata. Quando si inizia il percorso per lavorare con questo dispositivo, vale la pena osservare che nel prodotto finale dell'unità mangOH sono coinvolti tre elementi. L'unità MangOH Red è la scheda vera e propria, Sierra Wireless è il produttore del modulo CF3, nonché il proprietario di AirVantage, vale a dire il cloud IoT in cui vengono memorizzati i dati provenienti dall'unità mangOH, e infine l'interfaccia a riga di comando (CLI) Legato, basata su Linux, utilizzata per il collegamento con l'unità mangOH. Nell'articolo, esaminerò a mano a mano ciascuno di tali elementi e le modalità di collegamento ai rispettivi forum.

    Visitare per primo il sito della Guida introduttiva a mangOH. È possibile selezionare i sistemi operativi Windows o Linux (anche Mac OS è compatibile, ma ne parlerò più avanti). A prescindere dal sistema operativo scelto, occorre comunque incorporare l'interfaccia CLI Legato tramite una macchina virtuale (Oracle VirtualBox) su Windows, o un add-on per lo sviluppo di Legato su Linux. Il Manuale di installazione per Windows e il Manuale di installazione per Linux sono risorse eccellenti durante l'installazione della macchina, quindi non riprodurrò qui le relative informazioni.

    Se si utilizza una macchina Linux a 64 bit, prestare attenzione al punto 6 a pagina 16 del Manuale di installazione per Linux.

    Occorre inoltre scaricare Developer Studio, disponibile per i sistemi operativi Windows, Linux e Mac. Secondo il sito Web di Sierra Wireless, "Developer Studio è l'ambiente di sviluppo integrato (IDE) di Sierra Wireless per il framework applicativo Legato". Ciò significa che per la creazione delle proprie app si hanno a disposizione due opzioni, vale a dire utilizzare un programma di testo base oppure servirsi di Developer Studio, uno strumento a base grafica che automatizza alcune delle operazioni di creazione dei file / delle cartelle. Ho scaricato Developer Studio per ciascun sistema operativo e ho incontrato un unico intoppo, vale a dire il requisito di Java 8 per Mac OS; per qualche motivo, l'installazione regolare di Java 8 non è stata sufficiente per l'esecuzione di Developer Studio, quindi in ultimo ho scaricato e installato il kit di sviluppo Java SE 8u151 Oracle.

    App campione e struttura dei file

    Una volta installata l'unità mangOH, il punto migliore per iniziare è Legato su Github. Scaricare o clonare la cartella Legato. Visitare su Github anche le spiegazioni relative alle App campione Legato per alcuni dei campioni scaricati. Il sito web delle app campione Legato è inoltre una risorsa eccellente per le spiegazioni "How To".

    Occorre prestare attenzione anche alla struttura dei file. Ogni applicazione ha la seguente struttura di directory/file:

    A seconda dell'applicazione, la struttura dei file può inoltre includere file dei tipi .API e .h. La parte sostanziosa della programmazione si trova nel file .c, mentre gli altri file contengono istruzioni destinate al compilatore per la creazione delle applicazioni.

    Esempio: app di testo di localizzazione GNSS

    L'applicazione tipo che illustra molto di ciò che l'unità mangOH Red è in grado di fare è quella che invia all'utente un testo con le coordinate dell'unità mangOH Red stessa. La struttura dei file è riportata sopra.

    Il codice per il file textLoc.c è riportato di seguito. Fare clic qui per visualizzare l'articolo Alla scoperta di nuovi prodotti in cui Randall Restle ha presentato per la prima volta l'unità mangOH Red.

    Copy
    textLoc.c
        //--------------------------------------------------------------------------------------------------
    /** @file textLoc.c
    *
    * This app illustrates a sample usage of ultra low power mode API. This app reads the current gps
    * location and then sends it as a text message to a destination cell phone number. Once the text
    * message has been sent, the device enters ultra low power mode. The device will wake up from
    * ultra low power mode after a configurable delay.
    *
    * @note This app expects destination cell number to be specified in environment variable section
    * of adef file. If nothing specified in environment variable, it will send message to a default
    * non-existent phone number.
    *
    * Copyright (C) Sierra Wireless Inc.
    */
    //--------------------------------------------------------------------------------------------------
    
    #include "legato.h"
    /* IPC APIs */
    #include "interfaces.h"
    
    //--------------------------------------------------------------------------------------------------
    /**
    * GPS timeout interval in minutes
    *
    * @note Please change this timeout value as needed.
    */
    //--------------------------------------------------------------------------------------------------
    #define GPSTIMEOUT 15
    
    //--------------------------------------------------------------------------------------------------
    /**
    * Default phone number to send location information.
    *
    * @note This is a non-existent phone number (ref:
    * https://en.wikipedia.org/wiki/Fictitious_telephone_number).
    */
    //--------------------------------------------------------------------------------------------------
    #define DEFAULT_PHONE_NO "8005550101"
    
    //--------------------------------------------------------------------------------------------------
    /**
    * Timer interval(in seconds) to exit from shutdown/ultralow-power state.
    *
    * @note Please change this interval as needed.
    */
    //--------------------------------------------------------------------------------------------------
    #define ULPM_EXIT_INTERVAL 30
    
    //--------------------------------------------------------------------------------------------------
    /**
    * Gpio used to exit from shutdown/ultralow-power state.
    *
    * @note Please change gpio number as needed.
    */
    //--------------------------------------------------------------------------------------------------
    #define WAKEUP_GPIO_NUM 38
    
    //--------------------------------------------------------------------------------------------------
    /**
    * Pointer to the null terminated string containing the destination phone number.
    */
    //--------------------------------------------------------------------------------------------------
    static const char *DestPhoneNumberPtr;
    
    //--------------------------------------------------------------------------------------------------
    /**
    * Attempts to use the GPS to find the current latitude, longitude and horizontal accuracy within
    * the given timeout constraints.
    *
    * @return
    * - LE_OK on success
    * - LE_UNAVAILABLE if positioning services are unavailable
    * - LE_TIMEOUT if the timeout expires before successfully acquiring the location
    *
    * @note
    * Blocks until the location has been identified or the timeout has occurred.
    */
    //--------------------------------------------------------------------------------------------------
    static le_result_t GetCurrentLocation(
    int32_t *latitudePtr, ///< [OUT] latitude of device - set to NULL if not needed
    int32_t *longitudePtr, ///< [OUT] longitude of device - set to NULL if not needed
    int32_t *horizontalAccuracyPtr, ///< [OUT] horizontal accuracy of device - set to NULL if not
    ///< needed
    uint32_t timeoutInSeconds ///< [IN] duration to attempt to acquire location data before
    ///< giving up. A value of 0 means there is no timeout.
    )
    {
    le_posCtrl_ActivationRef_t posCtrlRef = le_posCtrl_Request();
    if (!posCtrlRef)
    {
    LE_ERROR("Can't activate the Positioning service");
    return LE_UNAVAILABLE;
    }
    
    le_result_t result;
    const time_t startTime = time(NULL);
    LE_INFO("Checking GPS position");
    while (true)
    {
    result = le_pos_Get2DLocation(latitudePtr, longitudePtr, horizontalAccuracyPtr);
    if (result == LE_OK)
    {
    break;
    }
    else if (
    (timeoutInSeconds != 0) &&
    (difftime(time(NULL), startTime) > (double)timeoutInSeconds))
    {
    result = LE_TIMEOUT;
    break;
    }
    else
    {
    // Sleep for one second before requesting the location again.
    sleep(1);
    }
    }
    
    le_posCtrl_Release(posCtrlRef);
    
    return result;
    }
    
    //--------------------------------------------------------------------------------------------------
    /**
    * Sends an SMS text message to the given destination with the given message content.
    *
    * @return
    * - LE_OK on success
    * - LE_FAULT on failure
    */
    //--------------------------------------------------------------------------------------------------
    static le_result_t SendTextMessage(
    const char *destinationNumberPtr, ///< [IN] Phone number to send the text message to as ASCII
    ///< values
    const char *messageBodyPtr ///< [IN] Text message body content
    )
    {
    le_result_t result = LE_OK;
    LE_INFO("Sending SMS");
    
    le_sms_MsgRef_t sms = le_sms_Create();
    
    if (le_sms_SetDestination(sms, destinationNumberPtr) != LE_OK)
    {
    result = LE_FAULT;
    LE_ERROR("Could not set destination phone number");
    goto sms_done;
    }
    
    if (le_sms_SetText(sms, messageBodyPtr) != LE_OK)
    {
    result = LE_FAULT;
    LE_ERROR("Could not set text message body");
    goto sms_done;
    }
    
    if (le_sms_Send(sms) != LE_OK)
    {
    result = LE_FAULT;
    LE_ERROR("Could not send SMS message");
    goto sms_done;
    }
    
    LE_INFO("SMS Message sent");
    
    sms_done:
    le_sms_Delete(sms);
    return result;
    }
    
    //--------------------------------------------------------------------------------------------------
    /**
    * Send the device location as a text message
    *
    * Attempts to send an SMS text message containing the current device location to the destination
    * phone number.
    *
    * @note
    * No failure notification is provided if location services or SMS send are unsuccessful.
    */
    //--------------------------------------------------------------------------------------------------
    static void SendSmsCurrentLocation(
    void
    )
    {
    char smsBody[LE_SMS_TEXT_MAX_LEN];
    int32_t latitude;
    int32_t longitude;
    int32_t horizontalAccuracy;
    
    const le_result_t result =
    GetCurrentLocation(&latitude, &longitude, &horizontalAccuracy, GPSTIMEOUT * 60);
    if (result == LE_OK)
    {
    snprintf(smsBody, sizeof(smsBody), "Loc:%d,%d", latitude, longitude);
    }
    else
    {
    strncpy(smsBody, "Loc:unknown", sizeof(smsBody));
    }
    SendTextMessage(DestPhoneNumberPtr, smsBody);
    }
    
    //--------------------------------------------------------------------------------------------------
    /**
    * Configure the boot source and shutdown MDM.
    */
    //--------------------------------------------------------------------------------------------------
    static void CfgShutDown
    (
    void
    )
    {
    // Boot after specified interval.
    if (le_ulpm_BootOnTimer(ULPM_EXIT_INTERVAL) != LE_OK)
    {
    LE_ERROR("Can't set timer as boot source");
    return;
    }
    
    // Boot on gpio. Please note this is platform dependent, change it when needed.
    if (le_ulpm_BootOnGpio(WAKEUP_GPIO_NUM, LE_ULPM_GPIO_LOW) != LE_OK)
    {
    LE_ERROR("Can't set gpio: %d as boot source", WAKEUP_GPIO_NUM);
    return;
    }
    
    // Initiate shutdown.
    if (le_ulpm_ShutDown() != LE_OK)
    {
    LE_ERROR("Can't initiate shutdown.");
    }
    }
    
    //--------------------------------------------------------------------------------------------------
    /**
    * Callback function to handle change of network registration state.
    */
    //--------------------------------------------------------------------------------------------------
    static void RegistrationStateHandler
    (
    le_mrc_NetRegState_t state, ///< [IN] Network registration state.
    void *contextPtr ///< [IN] Context pointer.
    )
    {
    switch(state)
    {
    case LE_MRC_REG_HOME:
    case LE_MRC_REG_ROAMING:
    LE_INFO("Registered");
    SendSmsCurrentLocation();
    LE_INFO("Now configure boot source and shutdown MDM");
    CfgShutDown();
    break;
    case LE_MRC_REG_SEARCHING:
    LE_INFO("Searching...");
    break;
    case LE_MRC_REG_NONE:
    LE_INFO("Not registered");
    break;
    case LE_MRC_REG_DENIED:
    LE_ERROR("Registration denied");
    break;
    case LE_MRC_REG_UNKNOWN:
    LE_ERROR("Unknown registration state");
    break;
    }
    }
    
    //--------------------------------------------------------------------------------------------------
    /**
    * Simulate entry into the current NetReg state by calling RegistrationStateHandler
    *
    * RegistrationStateHandler will only be notified of state change events. This function exists to
    * simulate the change into the current state.
    */
    //--------------------------------------------------------------------------------------------------
    static void SimulateNetRegStateChangeToCurrentState(
    void *ignoredParam1, ///< Only exists to allow this function to conform to the
    ///< le_event_DeferredFunc_t declaration
    void *ignoredParam2 ///< Only exists to allow this function to conform to the
    ///< le_event_DeferredFunc_t declaration
    )
    {
    le_mrc_NetRegState_t currentNetRegState;
    LE_FATAL_IF(le_mrc_GetNetRegState(¤tNetRegState) != LE_OK, "Couldn't get NetRegState");
    RegistrationStateHandler(currentNetRegState, NULL);
    }
    
    //--------------------------------------------------------------------------------------------------
    /**
    * Get the destination phone number.
    **/
    //--------------------------------------------------------------------------------------------------
    static void GetDestinationCellNo
    (
    void
    )
    {
    DestPhoneNumberPtr = getenv("DEST_CELL_NO");
    if (!DestPhoneNumberPtr)
    {
    LE_WARN(
    "No destination cell number is specified. Using a default non-existent number");
    DestPhoneNumberPtr = DEFAULT_PHONE_NO;
    }
    
    LE_INFO("Destination phone number = %s", DestPhoneNumberPtr);
    }
    
    
    COMPONENT_INIT
    {
    char version[LE_ULPM_MAX_VERS_LEN + 1];
    
    LE_INFO("TextLoc started");
    
    // Get ultra low power manager firmware version
    LE_FATAL_IF(
    le_ulpm_GetFirmwareVersion(version, sizeof(version)) != LE_OK,
    "Failed to get ultra low power firmware version");
    LE_INFO("Ultra Low Power Manager Firmware version: %s", version);
    
    // Now check whether boot was due to timer expiry.
    if (le_bootReason_WasTimer())
    {
    LE_INFO("Booted from timer, not sending another text message.");
    }
    else if (le_bootReason_WasGpio(WAKEUP_GPIO_NUM))
    {
    LE_INFO("Booted from GPIO, not sending another text message.");
    }
    else
    {
    // Get the destination phone number
    GetDestinationCellNo();
    
    // Register a callback handler for network registration state.
    le_mrc_AddNetRegStateEventHandler(
    (le_mrc_NetRegStateHandlerFunc_t)RegistrationStateHandler, NULL);
    le_event_QueueFunction(&SimulateNetRegStateChangeToCurrentState, NULL, NULL);
    }
    }
    The textLoc.adef file is:
    textLoc.adef  
    sandboxed: false
    
    version: 1.0.0
    maxFileSystemBytes: 512K
    
    executables:
    {
    textloc = ( textLocComponent )
    }
    
    processes:
    {
    envVars:
    {
    LE_LOG_LEVEL = DEBUG
    // This is a non-existent fictitious phone number. Change it to a valid phone number.
    DEST_CELL_NO = 8005550101
    }
    run:
    {
    ( textloc )
    }
    maxCoreDumpFileBytes: 512K
    maxFileBytes: 512K
    }
    
    bindings:
    {
    textloc.textLocComponent.le_mrc -> modemService.le_mrc
    textloc.textLocComponent.le_posCtrl -> positioningService.le_posCtrl
    textloc.textLocComponent.le_pos -> positioningService.le_pos
    textloc.textLocComponent.le_sms -> modemService.le_sms
    textloc.textLocComponent.le_ulpm -> powerMgr.le_ulpm
    textloc.textLocComponent.le_bootReason -> powerMgr.le_bootReason
    }
    
    The Component.cdef:
    Component.cdef  
    requires:
    {
    api:
    {
    modemServices/le_mrc.api
    modemServices/le_sms.api
    positioning/le_posCtrl.api
    positioning/le_pos.api
    le_ulpm.api
    le_bootReason.api
    }
    }
    
    sources:
    {
    textLoc.c
    }
    Makefile:
    Makefile  
    TARGETS := $(MAKECMDGOALS)
    
    .PHONY: all $(TARGETS)
    all: $(TARGETS)
    
    $(TARGETS):
    mkapp -v -t $@ \
    textLoc.adef
    
    clean:
    rm -rf _build_* *.update
    

Informazioni su questo autore

Image of Curtis Johnson

Curtis Johnson, un tecnico associato di ingegneria delle applicazioni presso DigiKey, dal 2017 aiuta i clienti a trovare risposta alle domande tecniche ed è in DigiKey dal 2015, dopo una carriera di 15 anni come bancario. Curtis ha conseguito un AAS in sistemi automatizzati di tecnologia elettronica, una laurea in psicologia (nessun nusso con il settore bancario o elettronico), un MBA con enfasi sulla contabilità, studi post-laurea in economia e finanza e dall'autunno 2018 è iscritto in un corso di laurea di primo livello in Informatica. Curtis sta approfondendo la sua comprensione dei sistemi embedded, RF, comunicazioni cellulari e molti altri aspetti. Curtis dedical il suo tempo libero alla famiglia, a leggere e studiare.

More posts by Curtis Johnson
 TechForum

Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.

Visit TechForum