element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Members
    Members
    • Benefits of Membership
    • Achievement Levels
    • Members Area
    • Personal Blogs
    • Feedback and Support
    • What's New on element14
  • Learn
    Learn
    • Learning Center
    • eBooks
    • STEM Academy
    • Webinars, Training and Events
    • More
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • More
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • More
  • Products
    Products
    • Arduino
    • Dev Tools
    • Manufacturers
    • Raspberry Pi
    • RoadTests & Reviews
    • Avnet Boards Community
    • More
  • 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
Test & Tools
  • Technologies
  • More
Test & Tools
Blog SCPI on a Linux Board - Letter of Intent
  • Blog
  • Forum
  • Documents
  • Events
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Test & Tools requires membership for participation - click to join
Blog Post Actions
  • Subscribe by email
  • More
  • Cancel
  • Share
  • Subscribe by email
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
Author: Jan Cumps
Date Created: 27 Apr 2018 5:41 PM
Views: 619
Likes: 14
Comments: 21
  • 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).

 

 

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 .

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
Anonymous

Top Comments

  • Jan Cumps
    Jan Cumps over 4 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 4 years ago +3

    Good luck Jan.

     

    DAB

  • Jan Cumps
    Jan Cumps over 4 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 4 years ago

    Some more progress: first contact from LabVIEW

     

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

    • Cancel
    • Up +2 Down
    • Reply
    • More
    • Cancel
Comment
  • Jan Cumps
    Jan Cumps over 4 years ago

    Some more progress: first contact from LabVIEW

     

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

    • Cancel
    • Up +2 Down
    • Reply
    • More
    • Cancel
Children
  • Jan Cumps
    Jan Cumps over 4 years ago in reply to Jan Cumps

    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.

    • Cancel
    • Up +4 Down
    • Reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 4 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
    • Up +3 Down
    • Reply
    • More
    • Cancel
  • shabaz
    shabaz over 4 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
    • Up +1 Down
    • Reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 4 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

    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
    • Up +2 Down
    • Reply
    • More
    • Cancel
  • shabaz
    shabaz over 4 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
    • Up +2 Down
    • Reply
    • More
    • Cancel
Element14

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 © 2022 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

  • Facebook
  • Twitter
  • linkedin
  • YouTube