element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Test & Tools
  • Technologies
  • More
Test & Tools
Blog SCPI on a Linux Board - Letter of Intent
  • Blog
  • Forum
  • Documents
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Test & Tools to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: Jan Cumps
  • Date Created: 27 Apr 2018 5:41 PM Date Created
  • Views 4939 views
  • Likes 14 likes
  • Comments 21 comments
  • pi
  • bbb
  • BeagleBone
  • raspberrypi
  • scpi
Related
Recommended

SCPI on a Linux Board - Letter of Intent

Jan Cumps
Jan Cumps
27 Apr 2018

I'm trying to build a SCPI shell for Linux.

I'd like to have it working over TCP/IP on a Raspberry Pi and a BeagleBone.

 

tl;dr It works. The rest of the blog series explains how to build a lab automation device that controls 8 outputs (2 of them relays), and read 8 inputs. With a Raspberry Pi and a PiFace Digital (2).

image

 

 

Here on element14, we've been playing with SCPI and microcontrollers. We have several instruments working on MSP432, Arduino and Hercules devices.

This time I'd like to get a Linux instrument up. To get some device independence, I'll try to make the source work on two different boards with different distros.

The program is expected to run as a background process.

 

I have a head start. My favourite SCPI library has a LwIP SCPI server example.

A relative head start, that is, because I have to find out how to get all the dependencies - I want to develop on a Windows PC image.

If this project fails, it'll be because of my develop for Linux skills.

 

related blog
SCPI on a Linux Board - Letter of Intent

SCPI on a Linux Board - Part 1: Proof of Concept

SCPI on a Linux Board - Part 2a: PiFace Digital C programming

SCPI on a Linux Board - Part 2b: PiFace Digital C++ programming
SCPI on a Linux Board - Part 3: TCP/IP Socket C++ programming
SCPI on a Linux Board - Part 4: TCP/IP SCPI and Instrument Service
SCPI on a Linux Board - Part 4b: TCP/IP SCPI and Instrument Service 100% Working
SCPI on a Linux Board - Part 4c: TCP/IP SCPI and Instrument Service - Run as a Daemon
SCPI on a Linux Board - Part 5a: LabVIEW Driver for LAB Switch: Open, Close and Switch functions
  • Sign in to reply

Top Comments

  • Jan Cumps
    Jan Cumps over 7 years ago in reply to Jan Cumps +4
    Yay! It works. Above is the capture of a LabVIEW back and forth communication - with the Raspberry Pi as a VISA TCP/IP device. *IDN? command sent, and the reply from the Pi arrived at LabVIEW.
  • DAB
    DAB over 7 years ago +3
    Good luck Jan. DAB
  • Jan Cumps
    Jan Cumps over 7 years ago in reply to Jan Cumps +3
    what's not working ok: even though I get a reply, the Visa Read block in LabVIEW throws a timeout error. when I close a connection (regardless of telnet, LabVIEW), the service on the Raspberry Pi goes…
Parents
  • Jan Cumps
    Jan Cumps over 7 years ago

    Some more progress: first contact from LabVIEW

     

    image

    I don't have the reply working in the LabVIEW flow yet - it works different than serial/usb. But things look good.

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 7 years ago in reply to Jan Cumps

    Yay!

     

    image

     

     

     

    It works. Above is the capture of a LabVIEW back and forth communication - with the Raspberry Pi as a VISA TCP/IP device.

    *IDN? command sent, and the reply from the Pi arrived at LabVIEW.

    • Cancel
    • Vote Up +4 Vote Down
    • Sign in to reply
    • More
    • Cancel
Comment
  • Jan Cumps
    Jan Cumps over 7 years ago in reply to Jan Cumps

    Yay!

     

    image

     

     

     

    It works. Above is the capture of a LabVIEW back and forth communication - with the Raspberry Pi as a VISA TCP/IP device.

    *IDN? command sent, and the reply from the Pi arrived at LabVIEW.

    • Cancel
    • Vote Up +4 Vote Down
    • Sign in to reply
    • More
    • Cancel
Children
  • Jan Cumps
    Jan Cumps over 7 years ago in reply to Jan Cumps

    what's not working ok:

     

    • even though I get a reply, the Visa Read block in LabVIEW throws a timeout error.
    • when I close a connection (regardless of telnet, LabVIEW), the service on the Raspberry Pi goes into a spin.

     

    I want to tackle these before writing implementation posts.

    • Cancel
    • Vote Up +3 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • shabaz
    shabaz over 7 years ago in reply to Jan Cumps

    Hi Jan!

     

    I can't help on the LabView portion, but if you've got the Pi portion of the code somewhere, I'd be happy to examine it in case something sticks out. In terms of general ideas for debugging, you're already using gdb so that's great, it might be worth compiling on the Pi directly once, just to 100% confirm you're linking to the same versions of libraries. Also, 'strace' is sometimes useful too, although it chucks out a lot of debug.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 7 years ago in reply to shabaz

    The code as it stands now. It's a server side socket program that listens and serves info to a tcp/ip client knocking on its port:

     

    /*
     ============================================================================
     Name        : main.c
     Author      : Jan Cumps
     Version     :
     Copyright   : free for all
     Description :
     ============================================================================
     */
    
    
    /* A simple server in the internet domain using TCP
       The port number is passed as an argument */
    #include 
    #include 
    #include 
    #include 
    
    
    #include "scpi/scpi.h"
    #include "scpi-def.h"
    
    
    int newsockfd;
    
    
    /** SCPI utilities
     *
     */
    
    
    size_t SCPI_Write(scpi_t * context, const char * data, size_t len) {
        (void) context;
        int n = write(newsockfd, data, len);
        if (n < 0) error("ERROR writing to socket");
        return n;
    }
    
    
    scpi_result_t SCPI_Flush(scpi_t * context) {
        (void) context;
    
    
        return SCPI_RES_OK;
    }
    
    
    int SCPI_Error(scpi_t * context, int_fast16_t err) {
        (void) context;
    
    
        fprintf(stderr, "**ERROR: %d, \"%s\"\r\n", (int16_t) err, SCPI_ErrorTranslate(err));
        return 0;
    }
    
    
    scpi_result_t SCPI_Control(scpi_t * context, scpi_ctrl_name_t ctrl, scpi_reg_val_t val) {
        (void) context;
    
    
        if (SCPI_CTRL_SRQ == ctrl) {
            fprintf(stderr, "**SRQ: 0x%X (%d)\r\n", val, val);
        } else {
            fprintf(stderr, "**CTRL %02x: 0x%X (%d)\r\n", ctrl, val, val);
        }
        return SCPI_RES_OK;
    }
    
    
    scpi_result_t SCPI_Reset(scpi_t * context) {
        (void) context;
    
    
        fprintf(stderr, "**Reset\r\n");
        return SCPI_RES_OK;
    }
    
    
    scpi_result_t SCPI_SystemCommTcpipControlQ(scpi_t * context) {
        (void) context;
    
    
        return SCPI_RES_ERR;
    }
    
    
    
    
    
    
    void error(char *msg)
    {
        perror(msg);
        exit(1);
    }
    
    
    int main(int argc, char *argv[])
    {
         int sockfd, portno, clilen;
         char buffer[256];
         struct sockaddr_in serv_addr, cli_addr;
         int n;
    
    
         SCPI_Init(&scpi_context,
                 scpi_commands,
                 &scpi_interface,
                 scpi_units_def,
                 SCPI_IDN1, SCPI_IDN2, SCPI_IDN3, SCPI_IDN4,
                 scpi_input_buffer, SCPI_INPUT_BUFFER_LENGTH,
                 scpi_error_queue_data, SCPI_ERROR_QUEUE_SIZE);
         if (argc < 2) {
             fprintf(stderr,"ERROR, no port provided\n");
             exit(1);
         }
         sockfd = socket(AF_INET, SOCK_STREAM, 0);
         if (sockfd < 0)
            error("ERROR opening socket");
         bzero((char *) &serv_addr, sizeof(serv_addr));
         portno = atoi(argv[1]);
         serv_addr.sin_family = AF_INET;
         serv_addr.sin_addr.s_addr = INADDR_ANY;
         serv_addr.sin_port = htons(portno);
         if (bind(sockfd, (struct sockaddr *) &serv_addr,
                  sizeof(serv_addr)) < 0)
                  error("ERROR on binding");
         listen(sockfd,5);
         clilen = sizeof(cli_addr);
         newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
         if (newsockfd < 0)
              error("ERROR on accept");
         while (1) {
             bzero(buffer,256);
             n = read(newsockfd,buffer,255);
             if (n < 0) {
            error("ERROR reading from socket");
             } else if (n > 0) {
                 printf("Here is the message: %s\n",buffer);
                 scpi_instrument_input(buffer, n);
    
    
             }
    
    
         }
    
    
         return 0;
    }

     

    My issue is in this small part:

     

         while (1) {
             bzero(buffer,256);
             n = read(newsockfd,buffer,255);
             if (n < 0) {
            error("ERROR reading from socket");
             } else if (n > 0) {
                 printf("Here is the message: %s\n",buffer);
                 scpi_instrument_input(buffer, n);
             }
         }

     

    As long as the client is connected, n = 0 when no data received from the client. All good image

    When the client (example unix telnet session) closes, the read() function always returns the value 32.

    Before I define a fix for that, I want to try and understand why that is.

     

    Before anyone thinks that I'm a server side network socket expert: I borrowed this from http://www.cs.rpi.edu/~moorthy/Courses/os98/Pgms/server.c

    Because that program doesn't loop (it waits for traffic, notifies and dies), it doesn't have the issue.

     

    I need to do some more studying ...

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • shabaz
    shabaz over 7 years ago in reply to Jan Cumps

    Hi Jan,

     

    It's a while since I looked at the POSIX socket API, so I'm not sure either, but it might be worth also testing that newsockfd does not equal 0 before trying the read operation, e.g.

     

    if (newsockfd) {
      n=read(newsockfd, buffer, 255);
    }

     

    From memory I think using 'select' API is a good method to handle acting as a TCP server, but I need to read up on it. I'll try to dig up some useful links. There are some good patterns to handling socket reads, I just need to find them.

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 7 years ago in reply to shabaz

    You may be on to something. I only call newsockfd() once at the start and assign it to a global variable (blush). So it will never be 0, but it may very well be invalid.

     

    I'll check if I have to reallocate each time, or if I have to check that handle's validity ...

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube