Close
0%
0%

Setting up the LinkIt C cross-compiler

Are you a "dyed in the wool" C programmer.
Love your Arduino but want something more powerful.
The LinkIt Smart MT7688 board may for you!

Similar projects worth following
What is LinkIt Smart 7688?

The LinkIt Smart 7688 is an open development board, based on the OpenWrt Linux distribution and MT7688.
It can be programmed in Python, Node.js and C programming language.

Features:
* Wi-Fi
* 580 MHz MIPS CPU.
* 32MB FLASH
* 128MB RAM
* Micro SD slot
* 22 GPIOs

What is not to like? It takes quite a bit of effort to set up!
That is what this project is about!

Setting up the LinkIt Smart MT7688 for  C Code

It took me nearly two weeks to to set it up. Hopefully you will not make the same mistakes that I made.

Before you Start

Although it may be possible to compile your projects on the board itself using the SD card, this is not the way it is done. You have to cross-compile on a 64 bit linux distribution.

So if your using Windows, find an old laptop and install a 64 bit distribution such as Mint.

You can set your LinkIt board up with Windows and use Python or Node.js but not for C/C++.

32 bit Linux Distributions

I wasted a week trying to get the C/C++ Compiler to work until I realised that it does not work on 32 bit linux distributions. You have been warned!

Get Started with the LinkIt Smart 7688 Development Board

Follow this tutorial:

https://docs.labs.mediatek.com/resource/linkit-smart-7688/en/get-started

If you are using Windows, check that you have  "Bonjour print services" installed, if not install it (you have been warned!).

The object of the tutorial is to update firmware (optional - I did not), set a password and set the LinkIt to "Station Mode".

In Station Mode, LinkIt uses your WiFi router to access the Internet and you can talk to your LinkIt via a "scp" (i.e. secure copy) and ssh (i.e. secure shell), and you get your Internet back!

Installing the Cross-Compiler

There are two candidate downloads:

OpenWrt SDK for C/C++ for Linux

and

C/C++ Toolchain for Linux

The SDK compiles "ipk" packages for the "opkg" installer:

https://docs.labs.mediatek.com/resource/linkit-smart-7688/en/tutorials/c-c++-programming/using-openwrt-sdk-to-build-c-c++-programs

You may need to install the following dependencies for the SDK:

$ sudo apt-get update

$ sudo apt-get install build-essential subversion libncurses5-dev zlib1g-dev gawk

$ sudo apt-get install gcc-multilib flex git-core gettext libssl-dev ccache

The SDK is a bit "upmarket" for Arduino style use (that is you just want to compile, upload and run a program rather than install a package). However, the SDK does create the executable file if you know where to look. But you need to deal with Makefile(s) and set package dependencies. You may need the package anyway as it has many pre-compiled libraries that you may need.

I used the Toolchain and copied the MRAA library and includes (used to access the GPIOs) from the SDK.

The third option is to download my LinkIt-cc archive (from my files area) and unpack it into your home directory.

Make Files

I am not an expert with make files (and this is my first try). The make file has been set up so I do not have to set the path environment variable (usually in .profile):

# Build target executable when user executes "make"
TARGET=mraa_blink

export STAGING_DIR=$(HOME)/LinkIt-cc
CC=$(HOME)/LinkIt-cc/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mipsel-openwrt-linux-uclibc-gcc
CFLAGS =-I.
CFLAGS+=-I$(HOME)/LinkIt-cc/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/usr/include
CFLAGS+=-I$(HOME)/LinkIt-cc/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/include
LDFLAGS =-L.
LDFLAGS+=-L$(HOME)/LinkIt-cc/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/usr/lib
LDFLAGS+=-L$(HOME)/LinkIt-cc/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/lib
LDFLAGS+=-lmraa -pthread -ldl

$(TARGET): $(TARGET).c
    $(CC) $(CFLAGS) -o $(TARGET).run $(TARGET).c $(LDFLAGS)

# remove object files and executable when user executes "make clean"
clean:
    rm $(TARGET).run

Note: the name of the make file has to be "Makefile".

How to use the make file

Set the target name:

TARGET=mraa_blink


Add any additional libraries

LDFLAGS+=-lmraa -pthread -ldl

(note: these are required for the mraa library)

Limitations

The main limitation of the make file is that it can only compile one C source file....

Read more »

uTimer.c

The timer demo code

x-csrc - 972.00 bytes - 10/29/2017 at 03:45

Download

Makefile

The makfile for the timer demo

makefile - 829.00 bytes - 10/29/2017 at 03:45

Download

GettingStarted.pdf

Setting up you LinkIt board.

Adobe Portable Document Format - 672.04 kB - 10/29/2017 at 03:06

Preview
Download

Adobe Portable Document Format - 79.80 kB - 10/29/2017 at 03:06

Preview
Download

LinkIt-cc.tar.7z

My LinkIt C Compiler directory.

x-7z-compressed - 33.83 MB - 10/29/2017 at 03:16

Download

View all 11 files

  • Update: Controlling the LED

    agp.cooper12/05/2017 at 12:01 0 comments

    Added a command line tool to set GPIOs

    Here is the tool in action on gpio0:

      root@mylinkit:~/Code# ./mraa_gpio.run -gpio 0 -dir out -val 1
      gpio0 write is 1
      root@mylinkit:~/Code# ./mraa_gpio.run -gpio 0 -dir in
      gpio0 read is 1
      root@mylinkit:~/Code# ./mraa_gpio.run -gpio 0 -dir out -val 0
      gpio0 write is 0
      root@mylinkit:~/Code# ./mraa_gpio.run -gpio 0 -dir in
      gpio0 read is 0
      root@mylinkit:~/Code# ./mraa_gpio.run -gpio 0 -dir close
      gpio0 closed

    So it works as expected. It also works on the WiFi LED (gpio44).

    I note that the LED logic is inverted.

    Here is the code:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdbool.h>
    #include <mraa.h>
    
    int main(int argc, char** argv)
    {
      // Pin No GPIO No  Function
      //     P1      43  Eth LED
      //     P8      20  UART TX2, PWM2
      //     P9      21  UART RX2, PWM3
      //    P10       2  I2S WS
      //    P11       3  I2S CLK
      //    P12       0  I2S SDI
      //    P13       1  I2S SDO
      //    P14      37  REF_CLK
      //    P15      44  WiFi LED
      //    P16      46  UART RX1
      //    P17      45  UART TX1
      //    P18      13  UART RX0
      //    P19      12  UART TX0
      //    P20       5  I2C SDA
      //    P21       4  I2C SCL
      //    P25       6  SPI CS
      //    P26      18  PWM0
      //    P27      19  PWM1
      //    P28      17  SPIS MOSI
      //    P29      16  SPIS MISO
      //    P30      15  SPIS SCK
      //    P31      14  SPIS CS
    
      bool gpioFlag=false;
      bool dirFlag=false;
      bool valFlag=false;
      bool helpFlag=false;
      int gpio=-1;
      int pin=-1;
      char dir[16]="";
      int val=-1;
    
      // Get parameters
      {
        long k;
        double f1;
        for (k=1;k<argc;k++) {
          if (strcmp(argv[k],"-pin")==0) {
            if (k+1<argc) sscanf(argv[k+1],"%lf",&f1);
            gpio=-1;
            pin=(int)f1;
            if (pin==1) gpio=43;
            if (pin==8) gpio=20;
            if (pin==9) gpio=21;
            if (pin==10) gpio=2;
            if (pin==11) gpio=3;
            if (pin==12) gpio=0;
            if (pin==13) gpio=1;
            if (pin==14) gpio=37;
            if (pin==15) gpio=44;
            if (pin==16) gpio=16;
            if (pin==17) gpio=45;
            if (pin==18) gpio=13;
            if (pin==19) gpio=12;
            if (pin==20) gpio=5;
            if (pin==21) gpio=4;
            if (pin==25) gpio=6;
            if (pin==26) gpio=18;
            if (pin==27) gpio=19;
            if (pin==28) gpio=17;
            if (pin==29) gpio=16;
            if (pin==30) gpio=15;
            if (pin==31) gpio=14;
            if (gpio!=-1) gpioFlag=true; 
          }
          if (strcmp(argv[k],"-gpio")==0) {
            gpioFlag=false;
            if (k+1<argc) sscanf(argv[k+1],"%lf",&f1);
            gpio=(int)f1;
            if ((gpio>=0)&&(gpio<=6)) {
              gpioFlag=true;
            } else if ((gpio>=12)&&(gpio<=21)) {
              gpioFlag=true;
            } else if (gpio==37) {
              gpioFlag=true;
            } else if ((gpio>=43)&&(gpio<=46)) {
              gpioFlag=true;
            }
            if (gpioFlag) gpio=(int)f1;
          }
          if (strcmp(argv[k],"-dir")==0) {
            dirFlag=true;
            if (k+1<argc) strcpy(dir,argv[k+1]);
          }
          if (strcmp(argv[k],"-val")==0) {
            valFlag=true;
            if (k+1<argc) sscanf(argv[k+1],"%lf",&f1);
            val=(int)f1;
            if (val<0) val=0;
            if (val>1) val=1;
          }
          if (strcmp(argv[k],"-help")==0) {
            helpFlag=true;
          }
        }
      }
    
      // Do it
      if ((gpioFlag)&&(dirFlag)&&(!helpFlag)) {
    
        mraa_gpio_context mraa_gpio=NULL;
        mraa_result_t mraa_res;
    
        mraa_gpio=mraa_gpio_init(gpio);
        if (mraa_gpio==NULL) {
          printf("gpio%d error\n",gpio);
          return(-1);
        }
        if (strcmp(dir,"in")==0) {
          mraa_gpio_dir(mraa_gpio,MRAA_GPIO_IN);
          printf("gpio%d read is %d\n",gpio,mraa_gpio_read(mraa_gpio));
          return (0);
        } else if (strcmp(dir,"close")==0) {
          mraa_res=mraa_gpio_close(mraa_gpio);
          if (mraa_res==MRAA_SUCCESS) {
            printf("gpio%d closed\n",gpio);
            return(0);
          } else {
            printf("gpio%d closed with error\n",gpio);
            return(-1);
          }
    
        } else if ((valFlag)&&(strcmp(dir,"out")==0)) {
          mraa_gpio_dir(mraa_gpio,MRAA_GPIO_OUT);
          mraa_gpio_write(mraa_gpio,val);
          printf("gpio%d write is %d\n",gpio,val);
          return(0);
        } else {
          return(-1);
        }
    
      } else {
    
        printf("mraa gpio - Written by Alan Cooper (agp.cooper@gmail.com)\n");
        printf("usage:    ./mraa_gpio.run -gpio n -pin n -dir [in|out|close] -val [0|1]\n");
        printf("options:  -gpio n              Set gpio number\n");
        printf("          -pin n               Set gpio number by using pin number\n");
        printf("          -dir [in|out|close]  Set gpio as input, output or close the gpio\n");
        printf("          -val [0|1]           Set gpio output value\n");
    
      }
    
    } 
    

    The command line format is:

    ./mraa_gpio.run  -gpio n  -pin n  -dir [in|out|close] ...

    Read more »

  • WiFi Server

    agp.cooper12/04/2017 at 10:08 0 comments

    Introduction

    WiFi Server

    A WiFi Server is like an IoT (Internet of Things) but it is only connected to your local WiFi network (rather than the Internet). So it can only be controlled by a "client" that is connected to your local WifI network. This in most cases is all you need to play with IoT at home.

    Web Server Options

    There are many ways to do this but after some research I selected "uhttpd" and "php". I am a beginner here (i.e. I have never used these programs before) so this selection may not be "optimal" (what ever that means!).

    "uhttpd" is the default OpenWrt web server and there is not much reason to go for anything better.

    PHP is a server-side scripting language designed primarily for web development but also used as a general-purpose programming language. It should be more than sufficient for IoT type applications.

    Task

    The task is pretty simple. Turn on or off the LED on the LinkIt board.

    Set Up

    Log on to the LinkIt

    You should know by now that you need to use a secure shell in a command window to work on the LinkIt, for example:

    ssh root@mylinkit.local 

    Installation of uhttpd

    It should be installed but it does not hurt to do the following:

    opkg update
    opkg install uhttpd
    

     Install PHP

    opkg install php5 php5-cgi php5-cli 
    

    The last package (php5-cli) allows you to run PHP scripts from the command line and is optional.

    Nano text editor

    I don't particularly like the "vi" text editor so I also install "nano":

    opkg install nano

    Edit the uhttpd configuration file

    nano /etc/config/uhttpd

    This is what my uhttpd configuration file looks like after being edited:

    config uhttpd 'main'
        list listen_http '0.0.0.0:80'
        list listen_http '[::]:80'
        list listen_https '0.0.0.0:443'
        list listen_https '[::]:443'
        option redirect_https '1'
        option home '/www'
        option rfc1918_filter '1'
        option max_requests '3'
        option max_connections '100'
        option cert '/etc/uhttpd.crt'
        option key '/etc/uhttpd.key'
        option cgi_prefix '/cgi-bin'
        option script_timeout '60'
        option network_timeout '30'
        option http_keepalive '20'
        option tcp_keepalive '1'
        option ubus_prefix '/ubus'
        list interpreter ".php=/usr/bin/php-cgi"
        option index_page 'index.php'
    
    config cert 'px5g'
        option days '730'
        option bits '1024'
        option country 'ZZ'
        option state 'Somewhere'
        option location 'Uknown'
        option commonname 'OpenWrt'
    

    I have added:

        list interpreter ".php=/usr/bin/php-cgi"
        option index_page 'index.php'

    Next, creating the Web Server Directory with:

    mkdir /www/php

    Add your "index.php" file to "/www/php", my index file contains: 

    <?php
      echo "Hello World, this is LinkIt running PHP!"
    ?>

    Now, restart the uhttp server: 

    /etc/init.d/uhttpd restart

    Finally, check the web-page by typing in a web browser:

    http://mylinkit.local/php/

     If it all works then magic!

    Controlling the LinkIt WiFi LED

    Unlike the Omega2 the LinkIt does not appear to have a "fast_gpio" command line tool. I could write my own code using the "mraa" library but I came across the "sysfs interface for user space" for control of GPIOs. This seems to be ideal for GPIO control for web applications. Basically on the command line you could do something like this:

    // Goto the sysfs-gpio directory
    cd /sys/class/gpio/
    
    // Create the gpio directory for gpio1
    echo 1 > export
    
    // Go into the gpio1 directory
    cd gpio1
    
    // Set the pin direction (i.e. in or out)
    echo out > direction
    
    // Set gpio1 high (i.e. 1)
    echo 1 > value
    
    // Set gpio1 low (i.e. 0)
    echo 0 > value
    
    // Done, go up a directory
    cd ..
    
    // Remove the gpio directory
    echo 1 > unexport
    

    This does work but not for the WiFi LED (i.e. gpio44), it appears as if as soon as you take control of the LED, the WiFi process takes back control. Code written using the "mraa" library would not have this problem.

    HTML Code for Controlling GPIO1

    Okay, change in task, control of GPIO1....

    Read more »

  • Simple Analog Input

    agp.cooper11/03/2017 at 02:02 0 comments

    Simple Analog Input

    Simple as in real simple!

    I had a look at two I2S or SPI analog chips:

    • ADS1115 (16 bit 3.3 ksp)

    and

    • MCP3008 (10Bit 200ksp)

    But I said simple as in real simple!

    Here is my first design:

    How does that work?

    1. The GPIO shorts the capacitor to ground (i.e. output low).
    2. the GPIO turns into an input and times the rising capacitor voltage until it exceeds 1.65 volts (i.e. 50% of 3.3v).

    The main limitation is that the input voltage must be more than 1.65 volts.

    The rise time of this network is in the order of 30 us to 150 us.

    Extending the range down to zero

    My second design:

    Dual Slope?

    If I connect the 91k resistor to another GPIO pin, I can measure the rise and fall times.

    This give a more accurate result.

    Lets get serious!

    During my Internet search I came across Sigma-Delta ADC:

    https://www.parallax.com/sites/default/files/downloads/AN008-SigmaDeltaADC-v1.0.pdf

    Here is the design:

    The second 1nF capacitor is to minimise supply voltage noise. The nominal voltage range is -0.825 V to +4.125 volts.

    The following web-pages have calculators for the resistor values but some thought is required for the capacitor values or the time constant:

    http://www.pulsedpower.net/Applets/Electronics/SigmaDeltaADC/SigmaDelta.html

    http://www.pulsedpower.net/Applets/Electronics/SigmaDeltaADC/SigmaDeltab.html

    Using with OpenWRT linux

    To start I would use a timer running at 4 uS intervals (I not sure how fast signal works!).

    This suggests for 8 bits precision (not accuracy!) a sample time of 1024us or a sample rate of 977 Hz.

    1. The timer interrupt would test the GPIO (in) and set the GPIO (out) the inverted value.
    2. The clock counter is incremented.
    3. If GPIO (out) was set high then the value counter is incremented.
    4. When the clock counter reaches 255, the value counter is exported (as the read value), and then both counters are reset.

    Here is my untested code (waiting for me to make up an ADC board):

    #include <stdio.h>
    #include <string.h>
    #include <signal.h>
    #include <sys/time.h>
    #include <unistd.h>
    #include <stdbool.h>
    #include <mraa.h>
    
    int running=true;
    void sig_handler(int signo)
    {
      if (signo==SIGINT) {
        printf("\nClosing down nicely\n");
        running=false;
      }
    }
    
    mraa_result_t result=MRAA_SUCCESS;
    mraa_gpio_context gpioIn=NULL;
    mraa_gpio_context gpioOut=NULL;
    
    // Sigma-Delta ADC
    volatile value=0;
    void timer_handler (int signum)
    {
      static int count=0;
      static int highCount=0;
      static int state=0;
    
      state=mraa_gpio_read(gpioIn);
      mraa_gpio_write(gpioOut,1-state);
      count++;
      if (state==1) highCount++;
      if (count>255) {
        count=0;
        value=highCount;
        highCount=0;
      }
    }
    
    int main(int argc, char** argv)
    {
      // Install ^C trap
      signal(SIGINT, sig_handler);
    
      // Install timer_handler as the signal handler for SIGVTALRM
      struct sigaction sa;
      struct itimerval timer;
      memset(&sa,0,sizeof(sa));
     sa.sa_handler=&timer_handler;
    ...
    Read more »

  • Elapsed Time

    agp.cooper11/02/2017 at 10:29 0 comments

    Elapsed Time

    There is a need for measuring elapsed time. This code seems to work well:

    #include <stdlib.h>
    #include <stdio.h>
    #include <sys/time.h>
    #include <mraa.h>
    
    int main(void) {
      double elapsedTime;
    
      struct timespec ts_start;
      struct timespec ts_end;
    
      // start timer
      clock_gettime(CLOCK_MONOTONIC, &ts_start);
    
      // do something
      usleep(1000000);
    
      // stop timer
      clock_gettime(CLOCK_MONOTONIC, &ts_end);
    
      // compute and print the elapsed time in millisec
      elapsedTime=(ts_end.tv_sec-ts_start.tv_sec)*1000.0;         // sec to ms
      elapsedTime+=(ts_end.tv_nsec-ts_start.tv_nsec)/1000000.0;   // nsec to ms
      printf("Elapsed time %lf ms\n",elapsedTime);
    
      // start timer
      clock_gettime(CLOCK_MONOTONIC, &ts_start);
      // stop timer
      clock_gettime(CLOCK_MONOTONIC, &ts_end);
    
      // compute and print the elapsed time in millisec
      elapsedTime=(ts_end.tv_sec-ts_start.tv_sec)*1000.0;         // sec to ms
      elapsedTime+=(ts_end.tv_nsec-ts_start.tv_nsec)/1000000.0;   // nsec to ms
      printf("Elapsed time adjustment %lf ms\n",elapsedTime);
    
    
      return 0;
    }

    It is pretty consistent:

    root@mylinkit:~/Code# ./elapsedTime.run
    Elapsed time 1000.084598 ms
    Elapsed time adjustment 0.001242 ms
    root@mylinkit:~/Code# ./elapsedTime.run
    Elapsed time 1000.079080 ms
    Elapsed time adjustment 0.001376 ms
    root@mylinkit:~/Code# ./elapsedTime.run
    Elapsed time 1000.083097 ms
    Elapsed time adjustment 0.001431 ms
    root@mylinkit:~/Code# ./elapsedTime.run
    Elapsed time 1000.081609 ms
    Elapsed time adjustment 0.001255 ms
    root@mylinkit:~/Code# ./elapsedTime.run
    Elapsed time 1000.079716 ms
    Elapsed time adjustment 0.001248 ms
    root@mylinkit:~/Code# ./elapsedTime.run
    Elapsed time 1000.080426 ms
    Elapsed time adjustment 0.001445 ms

    The "elsaped time adjustment (~1.33 uS) is the time it takes to do the measurement.

    The "usleep()" function is off about 81 us (over 1000000 uS) which seem consistent with the definition that:

    • " The usleep() function suspends execution of the calling thread for (at least) usec microseconds. The sleep may be lengthened slightly by any
      system activity or by the time spent processing the call or by the granularity of system timers."

    So all good!

    AlanX

  • Analog IO

    agp.cooper10/30/2017 at 03:06 0 comments

    Analog IO

    I was wondering what the conversion speed and other specifications for the LinkIt were?

    I came across this webpage (for the Intel Edison Galileo):

    https://navinbhaskar.wordpress.com/2016/04/25/cc-on-intel-edisongalileo-part4adc/

    It had an example of reading a potentiometer (i.e. a variable resistor) that controlled (i.e. PWM) the brightness of an LED.

    The page reinforced the idea of properly shutting down the program. Okay, I get the message.

    I was a bit surprised it compiled because of the problem with mraa_hello of "common.h" not being referenced in "mraa.h" but then I remembered that if you call any other set of functions they contain "common.h".

    I don't understand the "(arg);" in the signal handler, it seems like some "compiler trick":

    // Signal handler used to stop this application cleanly
    void handler(int arg) {
      (arg);
      keepRunning = 0;
    }

    But otherwise the code is straight forward.

    I was also a little surprised that "usleep(500);" did not ask for the "unistd.h" header.

    But after I checked the "mraa" function headers I found:

    • #include <stdio.h>
    • #include <unistd.h>
    • #include <stdint.h>

    So problem solved, and now I understand the difference between <*.h> and "*.h", the first version reads any additional include files in the include file while the second version does not.

    Here is my slightly edited version:

    #include <stdio.h>
    #include <stdint.h>
    #include <mraa.h>
    #include <signal.h>
    #include <unistd.h>
    
    #define PWM_PIN      5                 // The pin where the LED is connected
    #define ADC_PIN      0                 // The ADC pin
    #define ADC_MAX   (1024.0)             // Maximum value output by a 10-bit ADC
    
    volatile int keepRunning;
    
    // Signal handler used to stop this application cleanly
    void handler(int arg) {
      (arg);
      keepRunning = 0;
    }
    
    
    int main(void) {
      mraa_pwm_context       pwmPin;     // The PWM pin context
      mraa_aio_context       adcPin;     // ADC pin context
        
      float                  intensity;  // Intensity with which LED is to glow
      float                  adcValue;   // Read ADC value
        
      // Step 1: Intialize the mraa system
      mraa_init();
        
      // Step 2: Initalize analog port 0 for ADC operation
      adcPin = mraa_aio_init(ADC_PIN);
        
      // Step 3: Initialize D5 for PWM operation
      pwmPin = mraa_pwm_init(PWM_PIN);
        
      // Step 4: Set the period on the PWM pin
      mraa_pwm_period_us(pwmPin, 5000);  // Set the period as 5000 us or 5ms
        
      /* Step 5: Enable the PWM pulse on the pin
      mraa_pwm_enable(pwmPin, 1);
       
      keepRunning = 1;
        
      /* 
       * Associate ctrl+c with our handler that clears the 'keepRunning'
       * flag that allows us to stop the PWM and ADC when exiting 
       */
      signal(SIGINT, handler);
        
      while (keepRunning) {
        // Step 6: Read the ADC value using the function 'mraa_aio_read()'
        adcValue = mraa_aio_read(adcPin);
        intensity = adcValue/ADC_MAX;
    
        // Step7: Set the intensity of the LED at port D5 using PWM
        mraa_pwm_write(pwmPin, intensity);
    
        usleep(500);
      }
        
      // Step 8: Stop the PWM and ADC when not required
      mraa_pwm_enable(pwmPin, 0);
      mraa_aio_close(adcPin);
            
      return 0;
    }

    Now if I read it correctly:

    • "PWM_PIN 5" is GPIO5 and maps to  Pin20 on the LinkIt.
    • "ADC_PIN 0" is GPIO0 and maps to  Pin12 on the LinkIt.

    I am not sure what the ARef (the analog reference voltage) is, I am going to guess it is 3.3v rather than 5v, as the CPU is running at 3.3v.

    I still don't know what the conversion speed is? I could measure it as it will likely be a blocking function.

    Okay, now I know why I can not find anything on ADC for the LinkIt Smart MT7688, it does not have ADC! The LinkIt Smart MT7688 Duo has ADC however but still the key specifications are missing.

    So if I want ADC I will have to use an external card.

    AlanX

  • How Fast?

    agp.cooper10/29/2017 at 07:39 0 comments

    How fast is the LinkIt?

     The answer is 312 ns +/- 5 ns or about 3.2 MHz. I coded this simple toggle program:

    #include <stdio.h>
    #include <string.h>
    #include "mraa/gpio.h"
    #include "mraa/common.h"
    #include <stdbool.h>
    
    int main(int argc, char** argv)
    {
      mraa_gpio_context gpio = NULL;
      const char* board_name = mraa_get_platform_name();
      int pinstate = 0;
    
      gpio = mraa_gpio_init(0);
      fprintf(stdout, "Welcome to libmraa\n  Version: %s\n  Running on %s (Ctrl+C to exit)\n", mraa_get_version(), board_name);
    
      if (gpio == NULL) {
        fprintf(stdout, "Could not initilaize gpio\n");
        return 1;
      }
      mraa_gpio_dir(gpio, MRAA_GPIO_OUT);
    
      pinstate = 0;
      while (true) {
        mraa_gpio_write(gpio, pinstate);
        pinstate = !pinstate;
      }
    
      return 0;
    }

    By comparison using the PINX command for an Arduino (Nano) was 375 ns +/-33ns:

    void setup() {                
      // initialize the digital pin as an output.
      pinMode(2, OUTPUT);     
    }
    
    void loop() {
      while (true) {
        PIND=B00000100;
      }
    }

    Not using PINX, it is still 375 ns but the duty cycle is about 33%:

    void setup() {                
      // initialize the digital pin as an output.
      pinMode(2, OUTPUT);     
    }
    
    void loop() {
      while (true) {
        PORTD|=B00000100;
        PORTD&=B11111011;
      }
    }

    If your wondering what straight Arduino code would look like (i.e. less the direct port manipulations):

    void setup() {                
      // initialize the digital pin as an output.
      pinMode(2, OUTPUT);     
    }
    
    int state=0;
    void loop() {
      while(true) {
        digitalWrite(2,state);
        state=!state;
      }
    }

    But now it takes 11.12 us! 

    Now there is upside for the LinkIt with direct port manipulations as well but this is a project for another day!

    AlanX

  • The Timer

    agp.cooper10/29/2017 at 02:49 0 comments

    The Timer

    The MT7688 has a timer but I cannot find documentation how to access it (even if that is appropriate). So I have written a simple timer (uTime.c) using <signal.h> and <sys/time.h>:

    #include <signal.h>
    #include <stdio.h>
    #include <string.h>
    #include <sys/time.h>
    
    void timer_handler (int signum) {
      static int count = 0;
      printf ("timer expired %d times\n", ++count);
    }
    
    int main () {
      struct sigaction sa;
      struct itimerval timer;
    
      // Install timer_handler as the signal handler for SIGVTALRM
      memset(&sa, 0, sizeof(sa));
      sa.sa_handler = &timer_handler;
      sigaction (SIGVTALRM, &sa, NULL);
    
      // Configure the timer to expire after 1 second
      timer.it_value.tv_sec = 1;
      timer.it_value.tv_usec = 0;
      // and every 1 second after that
      timer.it_interval.tv_sec = 1;
      timer.it_interval.tv_usec = 0;
      // Start a virtual timer
      //   It counts down whenever this process is executing
      setitimer (ITIMER_VIRTUAL, &timer, NULL);
    
      // Do something that can be interrupted
      while (1);
     }

    The code should be good for microsecond timing but I have not tested it.

    Example Run

    alanx@alanx ~/LinkIt-cc/uTimer $ make

    /home/alanx/LinkIt-cc/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mipsel-openwrt-linux-uclibc-gcc -I. -I/home/alanx/LinkIt-cc/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/usr/include -I/home/alanx/LinkIt-cc/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/include -o uTimer.run uTimer.c -L. -L/home/alanx/LinkIt-cc/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/usr/lib -L/home/alanx/LinkIt-cc/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/lib -lmraa -pthread -ldl

    alanx@alanx ~/LinkIt-cc/uTimer $ ls -lah

    total 28K
    drwxrwxr-x 2 alanx alanx 4.0K Oct 29 09:53 .
    drwxr-xr-x 8 alanx alanx 4.0K Oct 29 09:02 ..
    -rw-rw-r-- 1 alanx alanx  829 Oct 29 09:03 Makefile
    -rw-rw-r-- 1 alanx alanx  295 Oct 29 09:11 uTimer01.c
    -rw-rw-r-- 1 alanx alanx  972 Oct 29 09:49 uTimer.c
    -rwxrwxr-x 1 alanx alanx 7.4K Oct 29 09:53 uTimer.run

    alanx@alanx ~/LinkIt-cc/uTimer $ scp uTimer.run root@mylinkit.local:~/Code/uTimer
    root@mylinkit.local's password:

    uTimer.run                                    100% 7534     7.4KB/s   00:00    

    alanx@alanx ~/LinkIt-cc/uTimer $ ssh root@mylinkit.local
    root@mylinkit.local's password:

    BusyBox v1.23.2 (2015-11-18 16:34:33 CET) built-in shell (ash)

      _______                     ________        __
     |       |.-----.-----.-----.|  |  |  |.----.|  |_
     |   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
     |_______||   __|_____|__|__||________||__|  |____|
              |__| W I R E L E S S   F R E E D O M
     -----------------------------------------------------
     CHAOS CALMER (15.05+linkit, r47501)
     -----------------------------------------------------
      * 1 1/2 oz Gin            Shake with a glassful
      * 1/4 oz Triple Sec       of broken ice and pour
      * 3/4 oz Lime Juice       unstrained into a goblet.
      * 1 1/2 oz Orange Juice
      * 1 tsp. Grenadine Syrup
     -----------------------------------------------------

    root@mylinkit:~# cd Code/uTimer

    root@mylinkit:~/Code/uTimer# ls -lah

    drwxr-xr-x    2 root     root        4.0K Oct 29 01:54 .
    drwxr-xr-x    6 root    ...

    Read more »

  • Access to the GPIOs

    agp.cooper10/29/2017 at 02:29 0 comments

    Access to the GPIOs

    The MRAA library is a low level skeleton for "communication" on linux devices.  It can be found here:

    https://iotdk.intel.com/docs/master/mraa/

    That is, "communication" as in GPIO, SPI, I2C, AIO (i.e. analog IO), PWM and UART (i.e. serial. Look there for examples and the "API" documentation.

    Note that the "Mraa Hello" example on the home page does not compile as the functions are found in common.h and not mraa.h. You need to '#include "mraa/common.h"' in the source code! Here is my version:

    #include "mraa.h"
    #include "mraa/common.h"
    int main(int argc, char** argv)
    {
        const char* board_name = mraa_get_platform_name();
        fprintf(stdout, "hello mraa\n Version: %s\n Running on %s\n", mraa_get_version(), board_name);
        mraa_deinit();
        return MRAA_SUCCESS;
    }

    Getting the pre-compiled library for the cross-compiler

    The mraa library and include files are not in the toolchain but they are in the SDK. Look in:

    • OpenWrt-SDK-ramips-mt7688_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/usr/lib

    and

    • OpenWrt-SDK-ramips-mt7688_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/usr/include

    The libraries are:

    Note that libmraa.so and libmraa.so.0 are symbolic links to libmraa.so.0.8.0 .

    The includes are:

    • mraa.h
    • mraa/aio.h
    • mraa/common.h
    • mraa/gpio.h
    • mraa/i2c.h
    • mraa/pwm.h
    • mraa/spi.h
    • mraa/types.h
    • mraa/uart.h

    I have added an archive to the files download area of this project for the mraa library for your convenience.

    An Example Run (Mraa hello)

    alanx@alanx ~/LinkIt-cc/mraa_hello $ make

    /home/alanx/LinkIt-cc/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mipsel-openwrt-linux-uclibc-gcc -I. -I /home/alanx/LinkIt-cc/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/usr/include -I /home/alanx/LinkIt-cc/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/include -o mraa_hello.run mraa_hello.c -L. -L/home/alanx/LinkIt-cc/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/usr/lib -L/home/alanx/LinkIt-cc/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/lib -lmraa -pthread -ldl
    alanx@alanx ~/LinkIt-cc/mraa_hello $ scp mraa_hello.run root@mylinkit.local:~/Code/mraa_hello

    root@mylinkit.local's password:

    mraa_hello.run                                100% 7562     7.4KB/s   00:00    

    alanx@alanx ~/LinkIt-cc/mraa_hello $ ssh root@mylinkit.local
    root@mylinkit.local's password:

    BusyBox v1.23.2 (2015-11-18 16:34:33 CET) built-in shell (ash)

      _______                     ________        __
     |       |.-----.-----.-----.|  |  |  |.----.|  |_
     |   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
     |_______||   __|_____|__|__||________||__|  |____|
              |__| W I R E L E S S   F R E E D O M
     -----------------------------------------------------
     CHAOS CALMER (15.05+linkit, r47501)
     -----------------------------------------------------
      * 1 1/2 oz Gin            Shake with a glassful
      * 1/4 oz Triple Sec       of broken ice and pour
      * 3/4 oz Lime Juice       unstrained into a goblet.
      * 1 1/2 oz Orange Juice
      * 1 tsp. Grenadine Syrup
     -----------------------------------------------------
    root@mylinkit:~# cd Code/mraa_hello

    root@mylinkit:~/Code/mraa_hello#...

    Read more »

View all 8 project logs

Enjoy this project?

Share

Discussions

agp.cooper wrote 12/05/2017 at 08:45 point

Hi Bartosz (and again),

Have a look at https://www.sparkfun.com/pages/wireless_guide for the various transceiver options available (I note that Sonnet is 433/915 MHz and that seem to match what hardware is available).

This web-page (https://en.wikipedia.org/wiki/ALOHAnet#ALOHA_protocol) offers some good ideas for collision recover protocols, assuming your are implementing some form of master/save packet system.

Also have a look at AX.25 (https://tapr.org/pub_ax25.html) for a documented packet system.

It also discusses collision recovery and round-table operations.

---

Long long time ago (mid 90s) I wrote a telephone-modem text-chat program that used a QuickCam. It would take a snapshot every minute (after a beep to let you compose yourself), and while you were typing it would update the screen. One difficulty I had was getting the software to decide who was the master and who as the slave. Basically the two programs would randomly take the master or slave role until one was master and one was slave. It sometime took a while for the "fight" to decide who was the winner!

AlanX

  Are you sure? yes | no

agp.cooper wrote 12/05/2017 at 06:31 point

Hi Bartosz (again),

The operating system is OpenWRT which is most likely the same as your WiFi router.

The board can be configured as a range extended and can manage ethernet connections (refer to the "Breakout for LinkIt Smart 7688").

So if your happy to spend the time exploring OpenWRT you may find what you want.

---

I have only recently made the jump from Windows to Linux so I don't have the same in-depth knowledge about the "ins and outs" of Linux as I did Windows. So I can't really provide much more help or suggested software. The range of options out there is rather bewildering.

---

I have been looking at IoT servers for a while now and again the range is rather bewildering.

I have decided to have a play with the Telegraph API.

I would be interested in your experiences in this area.

AlanX 

  Are you sure? yes | no

agp.cooper wrote 12/05/2017 at 06:13 point

Hi Bartosz,

While the LinkIt has been optimised for low power, it is not low power WiFi.

Typical power consumption 275 mA.

I am not familiar with Low Radiation (implying low power) WiFi but I might suggest looking at the old fashion serial radio link adapters.

These are typically 433MHz, 4mA power consumption and range in the order of 50m.

I think the data rate is about 4kB/s which is slow but for remote sensing it would be fine.

I tested WiFi range a few years ago (using the ESP8266) but only got 20 m.

If you running multiple sensors then that would be interesting!?

Perhaps some form of time-share (round robin?) or polling?

I have tried BlueTooth but I found it unreliable (with Windows).

AlanX

  Are you sure? yes | no

Bartosz wrote 12/04/2017 at 13:50 point

is possible add LORAWAN? to this machine and ethernet?

look at gotenna and sonnet , ideal but we need open source alternative

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates