如何使用树莓派 连接千寻开发板开发高精度应用

3 篇文章 0 订阅
1 篇文章 0 订阅

 

烧录Raspbian官方Linux固件版本,设置无线连接和远程登录(SSH)后开始集成千寻SDK。

此处如有问题请参考树莓派官方说明:
点击下载千寻位置树莓派SDK: https://bbs.qxwz.com/job.php?action=download&aid=1501

1、下载后解压

2.    编辑demo_main.c,将你申请到的千寻位置FindM Pro账号信息输入到这个文件里面

登录千寻位置官网控制中心(https://www.qxwz.com/),找到FindM Pro服务器实例,简单起见将设备服务号绑定方式设置为自动绑定,设备激活方式设置为自动激活。也可以按需设置。

DEVICE_ID和DEVICE_TYPE一行可以不变,也可以随意指定。如果在这个服务实例下面有多个账号,一个账号过期后如果需要继续使用另一个账号,需要在千寻位置账号端做解绑操作。

 

MC120_SERIAL_DEV为千寻开发板连接到树莓派的串口设备号,需通过如下命令获取:

保存退出

3.    编译SDK

4.    运行

如下图,是已经得到了高精度固定解:

 

/*
 * Copyright (c) 2018 Qianxun SI Inc. All rights reserved.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include "qxwz_sdk_hl.h"

//this is fake account info,please use the corrent to replace it.

#define APPKEY                  "123451"
#define APPSECRET               "61377185f39e5abf7c1eb1dba30dc6224efaf368a70a89653abde13f991c84af"
#define DEVICE_ID               "ID01"
#define DEVICE_TYPE             "typeA"

#define MC120_TYPE_M              0
#define MC120_TYPE_A              1

//root working dir which QXWZ SDK has write/read permission
#define ROOT_DIR                "./data/"
//NOTE:Magic Cube Device Node, please use the correct dev node according to your platform.
#define MC120_SERIAL_DEV         "/dev/ttyUSB0"
#define DEFAULT_SERIAL_BAUT     (115200)
#define DEFAULT_MC120M_BAUT     (9600)
// since the MC120_TYPE_M device only ouput nmea sentence in 1HZ(1000ms).
#define SERIAL_TIME_OUT_MS      (1050)

#define QXLOGI printf
#define QXLOGE printf

//commands to config ublox for MC120M, send these commands to MC120M before inject magic cubic data to QXWZ SDK
static unsigned char cmd10[] = { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0x02, 0x15, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x28, 0x4E };	//1 02-15 RXM-RAWX    16
static unsigned char cmd13[] = { 0xB5, 0x62, 0x06, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0xD0, 0x08, 0x00, 0x00, 0x00, 0xC2, 0x01, 0x00, 0x07, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x7E };	// 115200
//static unsigned char cmd15[] = { 0xB5, 0x62, 0x06, 0x3E, 0x34, 0x00, 0x00, 0x00, 0x20, 0x06, 0x00, 0x08, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x08, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x01, 0x05, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x01, 0x06, 0x08, 0x0E, 0x00, 0x00, 0x00, 0x01, 0x01, 0x14, 0xE1};	//GPS+BD
static unsigned char cmd15[] = { 0xB5, 0x62, 0x06, 0x3E, 0x3C, 0x00, 0x00, 0x00, 0x20, 0x07, 0x00, 0x08, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x04, 0x08, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x08, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x01, 0x05, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01, 0x01, 0x06, 0x08, 0x0E, 0x00, 0x00, 0x00, 0x01, 0x01, 0x2E, 0x75};	//GPS+BD+QZSS

static unsigned char cmd22[] = { 0xB5, 0x62, 0x06, 0x01, 0x03, 0x00, 0x01, 0x06, 0x01, 0x12, 0x4F };	//NAV_SOL
static unsigned char cmd23[] = { 0xB5,0x62,0x06,0x31,0x20,0x00,0x00,0x01,0x00,0x00,0x32,0x00,0x00,0x00,0x40,0x42,0x0F,0x00,0x40,0x42,0x0F,0x00,0x00,0x00,0x00,0x00,0xA0,0x86,0x01,0x00,0x00,0x00,0x00,0x00,0xF7,0x00,0x00,0x00,0xCA,0xB6 };//PPS
static unsigned char cmd24[] = {0xB5,0x62,0x06,0x08,0x06,0x00,0xC8,0x00,0x01,0x00,0x01,0x00,0xDE,0x6A};//5HZ
static unsigned char cmd25[] = {0xb5, 0x62, 0x06, 0x01, 0x08, 0x00, 0x02, 0x13, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x25, 0x3d}; //sub-frame


static int g_serial_fd = 0;//handler of serial device.
static QXWZSdkConfig default_cfg = {0}; //default config of QXSDK.

static int hl_main_opt(const char *dev, int type);
static int do_sdk_loop(int serial_fd, QXWZSdkConfig *pcfg);

/**
 *  change baut rate and set flags.
 */
static int set_serial_opt(int fd, int nSpeed, int nBits, char nEvent, int nStop)
{
    QXLOGI("Enter \n");
    struct termios newtio = {0};

    newtio.c_cflag  |=  CLOCAL | CREAD;
    newtio.c_cflag &= ~CSIZE;
    newtio.c_iflag &= ~( IXON | IXOFF | IXANY | ICRNL | INLCR | IGNCR );//for linux

    switch ( nBits ) {
    case 7:
        newtio.c_cflag |= CS7;
        break;
    case 8:
        newtio.c_cflag |= CS8;
        break;
    }

    switch ( nEvent ) {
    case 'O':
        newtio.c_cflag |= PARENB;
        newtio.c_cflag |= PARODD;
        newtio.c_iflag |= (INPCK | ISTRIP);
        break;
    case 'E':
        newtio.c_iflag |= (INPCK | ISTRIP);
        newtio.c_cflag |= PARENB;
        newtio.c_cflag &= ~PARODD;
        break;
    case 'N':
        newtio.c_cflag &= ~PARENB;
        break;
    }

    switch ( nSpeed ) {
    case 2400:
        cfsetispeed(&newtio, B2400);
        cfsetospeed(&newtio, B2400);
        break;
    case 4800:
        cfsetispeed(&newtio, B4800);
        cfsetospeed(&newtio, B4800);
        break;
    case 9600:
        cfsetispeed(&newtio, B9600);
        cfsetospeed(&newtio, B9600);
        break;
    case 115200:
        cfsetispeed(&newtio, B115200);
        cfsetospeed(&newtio, B115200);
        break;
    case 230400:
        cfsetispeed(&newtio, B230400);
        cfsetospeed(&newtio, B230400);
        break;
    default:
        cfsetispeed(&newtio, B9600);
        cfsetospeed(&newtio, B9600);
        break;
    }
    
    if ( nStop == 1 )
        newtio.c_cflag &=  ~CSTOPB;
    else if ( nStop == 2 )
        newtio.c_cflag |=  CSTOPB;

    newtio.c_cc[VTIME]  = 0;
    newtio.c_cc[VMIN] = 1;

    newtio.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);//for linux
    newtio.c_oflag &= ~OPOST;/*No Output Processing*/

    tcflush(fd, TCIOFLUSH);
    if ((tcsetattr(fd, TCSANOW, &newtio)) != 0) {
        perror("com set error");
        return -1;
    }

    QXLOGI("Leave \n");
    return 0;
}

/**
 *  make sure send out the whole frame.
 */
static void send_cmd2mc(int fd, unsigned char *cmd, int len)
{
    int offset = 0;
    size_t wcnt = 0;
    int total = len;

    do {
        wcnt = write(fd, cmd + offset, total);
        if (wcnt <= 0) {
            QXLOGI("write cmd to ublox failed....\n");
            usleep(1000);
            continue;
        } else {
            offset += wcnt;
            total -= wcnt;
        }
    } while (total > 0);

}

/**
 *  read data from seiral in noblock mode,and inject the data to QX NSDK.
 */
static int serial_poll(int serial_fd, QXWZSdkInterface *sdk_hl)
{
    fd_set input;
    int max_fd;
    int n;
    unsigned char data[4096];
    struct timeval  tv;

    while (1) {
        /* Initialize the input set */
        FD_ZERO(&input);
        FD_SET(serial_fd, &input);

        max_fd = serial_fd + 1;

        tv.tv_sec = SERIAL_TIME_OUT_MS / 1000;
        tv.tv_usec = (SERIAL_TIME_OUT_MS % 1000) * 1000;

        /* Do the select */
        n = select(max_fd,  &input, NULL, NULL, &tv);

        /* See if there was an error */
        if (n < 0) {
            perror("select failed");
//            break;
            continue;
        } else if (n == 0) {
            QXLOGE("serial read timeout in :%d (ms) \n", SERIAL_TIME_OUT_MS);
        } else {
            /* We have input */
            if (FD_ISSET(serial_fd, &input)) {
                size_t len = read(serial_fd, data, sizeof(data));
                if (sdk_hl && (len > 0) ) {
                    sdk_hl->inject_gnss_data(data, len);
                }

            }

        }
    }

    return 0;
}

/**
 *  @seiral_dev: the device name of the seiral in linux host.
 *  @type: MC120_TYPE_M or MC120_TYPE_A.
 */
static int hl_main_opt(const char *serial_dev, int type)
{
    QXLOGI("Enter \n");
    int ret;
    int set_gps;
    int serial_fd;
    QXWZSdkConfig * pcfg = &default_cfg;
    int baut = DEFAULT_SERIAL_BAUT;

    default_cfg.size           = sizeof(QXWZSdkConfig);
    default_cfg.log_enable     = 1;
    default_cfg.apply_scenario = QXWZ_GNSS_APPLY_SCENE_AUTOROOF;//customer should set this args by their scenario.
    sprintf(default_cfg.app_key, "%s", APPKEY);
    sprintf(default_cfg.app_secret, "%s", APPSECRET);
    sprintf(default_cfg.device_id, "%s", DEVICE_ID);
    sprintf(default_cfg.device_type, "%s", DEVICE_TYPE);
    sprintf(default_cfg.root_dir, "%s", ROOT_DIR);
    sprintf(default_cfg.socket_dir, "%s", "/tmp");
    sprintf(default_cfg.cfg_filename,"./%s","testCfg.ini");


    QXLOGI("current account info: %s %s %s %s \n",
           pcfg->app_key,
           pcfg->app_secret,
           pcfg->device_id,
           pcfg->device_type);

    QXLOGI("opening device :%s \n", serial_dev);

    /* O_RDWR Read/Write access to serial port           */
    /* O_NOCTTY - No terminal will control the process   */
    /* O_NDELAY -Non Blocking Mode,Does not care about-  */
    /* -the status of DCD line,Open() returns immediatly */
    serial_fd = open(serial_dev, O_RDWR | O_NONBLOCK | O_NOCTTY); //open serial
    if (serial_fd == -1) {
        QXLOGI("open :%s failed \n", serial_dev);
        return -1;
    }

    /* NOTE: MUST CONFIG MC120M BY THESE COMMANDS BEFORE INJECT SERIAL DATA to QXWZ SDK */
    if (type == MC120_TYPE_M) {
        baut = DEFAULT_MC120M_BAUT;
        QXLOGI("communicate baut is %d \n", baut);
        set_gps = set_serial_opt(serial_fd, baut, 8, 'N', 1); //setting serial attribution
        if (set_gps == -1) {
            QXLOGI("config serial device failed on setting \n");
            return -1;
        }
        QXLOGI("start reading... \n");

        //configure for the MC120_TYPE_M module
        QXLOGI("configure the device....\n");
        sleep(1);
        send_cmd2mc(serial_fd, cmd10, sizeof(cmd10));
        usleep(100000);
        send_cmd2mc(serial_fd, cmd15, sizeof(cmd15));
        usleep(100000);
        send_cmd2mc(serial_fd, cmd25, sizeof(cmd25));
        usleep(100000);
        send_cmd2mc(serial_fd, cmd22, sizeof(cmd22));
        usleep(100000);
        send_cmd2mc(serial_fd, cmd23, sizeof(cmd23));
        usleep(100000);
        send_cmd2mc(serial_fd, cmd13, sizeof(cmd13)); //change baud rate to 115200
        sleep(1);
        QXLOGI("configure over\n");

        close(serial_fd);
        QXLOGI("re-opening device %s\n", serial_dev);
        serial_fd = open(serial_dev, O_RDWR | O_NONBLOCK | O_NOCTTY); //open serial
        if (serial_fd == -1) {
            QXLOGI("open :%s failed \n", serial_dev);
            return -1;
        }

    }

    baut = DEFAULT_SERIAL_BAUT;
    QXLOGI("communicate baut is %d \n", baut);
    set_gps = set_serial_opt(serial_fd, baut, 8, 'N', 1); //CHANG BUAD
    if (set_gps == -1) {
        QXLOGI("failed to change baut:%d \n", baut);
        return -1;
    }

    g_serial_fd = serial_fd;
    /* After setting serial device, here start to read data & inject data to QXSDK  */
    ret = do_sdk_loop(serial_fd, pcfg);
    
    close(serial_fd);
    g_serial_fd = 0;

    QXLOGI("Leave");
    return ret;
}

//TODO: User should implement this callback if want to get position information by NMEA
static void cb_fill_nmea_info(QXGnssUtcTime time, const char* nmea, int len)
{
    if (nmea) {
        QXLOGI("nmea:%s", nmea);
    }
}

//TODO: User should implement this callback if want to get position information by paramter
static void cb_fill_position(QXWZGnssLocation *pos)
{
    if (pos) {
        QXLOGI("posflag:%d \n", pos->posflag);
    }
}

//NOTE: Write raw data back to Magic Cube device
static void cb_fill_raw_data(unsigned char *buf, int len)
{
    if (buf) {
        QXLOGI("len:%d \n", len);
    }

    if (g_serial_fd > 0) {
        send_cmd2mc(g_serial_fd, buf, len);
    }
}

//Notify status of SDK
static void cb_status_response(QXWZSdkStatus status)
{
    QXLOGI("status:%d \n", status);
}

/*  
 * This is demonstrating the API using.
 */
int do_sdk_loop(int serial_fd, QXWZSdkConfig* pcfg)
{
    int ret;
    const QXWZSdkInterface *sdk_hl = NULL;
    QXWZSdkCallbacks cbs;
    memset(&cbs, 0, sizeof(QXWZSdkCallbacks));
    cbs.size            = sizeof(cbs);
    cbs.fill_nmea_info  = cb_fill_nmea_info;
    cbs.fill_position   = cb_fill_position;
    cbs.fill_raw_data   = cb_fill_raw_data;
    cbs.status_response = cb_status_response;

    sdk_hl = getQXWZSdkInterface();
    //User should notify SDK of network status immediately once the network changes.
    //sdk_hl->update_conn_status(QXWZ_NET_TYPE_WIFI);
    sdk_hl->init(&cbs, pcfg);
    sdk_hl->start();


    /* [raw] => [QXSDK] */
    ret = serial_poll(serial_fd, (QXWZSdkInterface *)sdk_hl);

    sdk_hl->stop();
    sdk_hl->cleanup();

    QXLOGI("Leave");
    return ret;
}

/* This is a demo, Users need to operate UART of MC120A/MC120M, and inject data from UART to QXWZ SDK,
 * and control the call sequence 
 */
int  main(int argc, char *argv[])
{
    return hl_main_opt(MC120_SERIAL_DEV, MC120_TYPE_M);
}

https://bbs.qxwz.com/read.php?tid=1222 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值