Run language file c in Python sricpt

Asked

Viewed 192 times

-1

I have an analog data acquisition file converted to digital values (in this case the temperature value of the LM35 sensor) with ADC Maxim 1203, I would now like to call the file in a Python script for later sending that value to a Mysql database, it is possible to run a file with extension . c of the C language in a Python script?

the code in C is this:

#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>

#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#define MAX1202_3_lsb 0.001
#define MAX124_lsb 0.004

static const char *device = "/dev/spidev0.0";
static uint8_t mode = SPI_MODE_0;
static uint8_t bits = 8;
static uint32_t speed = 500000;
static uint16_t delay = 0;
static uint8_t deselect = 0;
static uint8_t input = 0;
static uint8_t verbose = 0;
static uint8_t unipolar = 8;
static uint8_t single = 4;
static uint8_t clock = 3;
static uint8_t newline = 1;
static uint8_t raw = 0;
static uint16_t bipolarconvert = 2047;
static float lsb = MAX1202_3_lsb;
static float fullscale = 0;
static uint8_t chip = 0 ; // chip type: 
//               0 for MAX1202 and MAX 1203
//               1 for MAX1204
static uint8_t inputtable[] = { 0, 64, 16, 80, 32, 96, 48, 112 };


static void pabort(const char *s)
{
    perror(s);
    abort();
}

static void vexit(const char *s)
{
    printf(s);
    if ( newline || verbose ) {
        printf("\n");
    }
    exit(1);
}

static void print_usage(const char *prog)
{
        printf("Usage: %s [-4Dscibkvnd]\n", prog);
        puts(
        "\n"
        " Maxim MAX1202 MAX1203 MAX1204 SPI adc utility\n"
        " Copyright (C) 2012  Alberto Panu\n"
        " http://www.panu.it/raspandmax/\n"
        "\n"
        " This program comes with ABSOLUTELY NO WARRANTY.\n"
        " This is free software, and you are welcome to redistribute it\n"
        " under certain conditions see GNU GPL v3\n"
        "\n"
        " Usage:\n"
        " -4 --max1204 select max1204 10 bit adc, default is max1202/3 12 bit\n"
        " -f --full full scale value, default are:\n"
        "      0 to 4.095 volt for unipolar mode\n"
        "      -2.048 to 2.047 volt for bipolar mode\n"
        " -D --device device to use (default /dev/spidev0.0)\n"
        " -s --speed SPI bus speed (Hz), default 500000\n"
        " -c --chipsel disable chipsel at read end, default don't disable\n"
        " -i --input chose input channel 0 to 7, default 0\n"
        " -b --bipolar set to bipolar mode, default unipolar, you need a -5V\n"
        "      power supply on pin 9!\n"
        " -k --clock set internal clock mode, default external\n"
        " -v --verbose print extra info usefoul for debug\n"
        " -r --raw raw mode ouput\n"
        " -n --newline suppress new line at non verbose output end\n"
        " -d --diff set to differential mode,\n"
        "      default is single ended, see table\n"
        "      for input channel selection:\n"
        "\n"
        "       ---------------\n"
        "      | Input l + | - |\n"
        "       ---------------\n"
        "      |   0   | 0 | 1 |\n"
        "       ---------------\n"
        "      |   1   | 2 | 3 |\n"
        "       ---------------\n"
        "      |   2   | 4 | 5 |\n" 
        "       ---------------\n"
        "      |   3   | 6 | 7 |\n"
        "       ---------------\n"
        "      |   4   | 1 | 0 |\n"
        "       ---------------\n"
        "      |   5   | 3 | 2 |\n"
        "       ---------------\n"
        "      |   6   | 5 | 4 |\n"
        "       ---------------\n"
        "      |   7   | 7 | 6 |\n"
        "       ---------------\n"
    );
    exit(1);
}

static void parse_opts(int argc, char *argv[])
{
    while (1) {
        static const struct option lopts[] = {
            { "input", 1, 0,'i' },
            { "full", 1, 0, 'f' },
            { "help", 0, 0, 'h' },
            { "speed", 1, 0, 's' },
            { "device", 1, 0, 'D' },
            { "verbose", 0, 0, 'v' },
            { "raw", 0, 0, 'r' },
            { "max1204", 0, 0, '4' },
            { "bipolar", 0, 0, 'b' },
            { "diff", 0, 0, 'd' },
            { "clock", 0, 0, 'k' },
            { "newline", 0, 0, 'n' },
            { NULL, 0, 0, 0 },
        };
        int c;

        c = getopt_long(argc, argv, "i:s:f:D:v4hbdknr", lopts, NULL);

        if (c == -1)
        break;

        switch (c) {

            case 'D':
            device = optarg;
            break;

            case 'i':
            input = atoi(optarg);
            break;

            case 'f':
            fullscale = atof(optarg);
            break;

            case 's':
            speed = atoi(optarg);
            break;

            case 'v':
            verbose = 1;
            break;

            case 'r':
            raw = 1;
            break;  

            case '4':
            chip = 1;
            break;

            case 'b':
            unipolar = 0;
            break;

            case 'd':
            single = 0;
            break;

            case 'k':
            clock = 2;
            break;

            case 'n':
            newline=0;
            break;

            default:
            print_usage(argv[0]);
            break;
        }
    }
}

int main(int argc, char *argv[])
{
    int fd;
    int ret = 0;

    parse_opts(argc, argv);

    if (speed > 2000000 || speed < 10000) {
        if ( verbose ) {
            vexit("Invalid speed, speed must be between 10000 and 2000000");
        } else {
            vexit("E");
        }
    }

    if ( input > 7 || input < 0 ) {
        if ( verbose ) {
            vexit("Invalid input, input must be between 0 and 7");
        } else {
            vexit("E");
        }
    } 

    fd = open(device, O_RDWR);
        if (fd < 0) {
            if ( verbose ) {
                printf("%s\n", device);
                pabort("can't open device");
            } else {
                vexit("E");
            }
        }

    /*
    * spi mode
    */

    ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
    if (ret == -1 ) {
        close(fd);
        if ( verbose ) {
            pabort("can't set spi mode");
        } else {
            vexit("E");
        }
    }

    ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
    if (ret == -1) {
        close(fd);
        if ( verbose ) {
            pabort("can't get spi mode");
        } else {
            vexit("E");
        }
    }

    /*
    * bits per word
    */
    ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
    if (ret == -1) {
        close(fd);
        if ( verbose ) {
            pabort("can't set bits per word");
        } else {
            vexit("E");
        }
    }

    ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
    if (ret == -1) {
        close(fd);
        if ( verbose ) {
            pabort("can't get bits per word");
        } else {
            vexit("E");
        }
    }

    /*
    * max speed hz
    */
    ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
    if (ret == -1) {
        close(fd);
        if ( verbose ) {
            pabort("can't set max speed hz");
        } else {
            vexit("E");
        }
    }
    ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
    if (ret == -1) {
        close(fd);
        if ( verbose ) { 
            pabort("can't get max speed hz");
        } else {
            vexit("E");
        }
    }

    if ( verbose ) {
        printf("device: %s\n", device);
        printf("spi mode: %d\n", mode);
        printf("bits per word: %d\n", bits);
        printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
        printf("input port %d\n", input);   
    }

    if ( verbose ) {
        if ( chip ) {
            printf("chip MAX1204\n");
        } else {
            printf("chip MAX1202 or MAX1203\n");
        }
    }

    uint8_t transmitbyte = 0b10000000;

    transmitbyte |= inputtable[input];

    if ( unipolar ) {
        transmitbyte |= unipolar;
        if ( verbose ) {
            printf("unipolar mode\n");
        }
    } else {
        if ( verbose ) {
            printf("bipolar mode\n");
        }
    }

    if ( single ) {
        if (verbose ) {
            printf("single ended mode\n");
        }
        transmitbyte |= single;
    } else {
        if ( verbose ) {
            printf("diferential mode");
        }
    }

    transmitbyte |= clock;
    if ( verbose ) {
        if ( clock == 3 ) {
            printf("external clock mode\n");
        } else {
            printf("internal clock mode\n");
        }
    }

    if ( verbose ) {
        printf("transmit byte %d\n", transmitbyte);
    }

    uint8_t tx[] = {
        transmitbyte, 0, 0
    };

//  printf("Array tx dimension: %d\n", ARRAY_SIZE(tx));

    uint8_t rx[ARRAY_SIZE(tx)] = {0,};

    struct spi_ioc_transfer tr = {
        .tx_buf = (unsigned long)tx,
        .rx_buf = (unsigned long)rx,
        .len = ARRAY_SIZE(tx),
        .delay_usecs = delay,
        .speed_hz = speed,
        .bits_per_word = bits,
        .cs_change = deselect,
    };

    ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
    if (ret < 1) {
        close(fd);
        if ( verbose ) {
            pabort("can't send spi message");   
        } else {
            vexit("E");
        }
    }

    close(fd);

    unsigned int first_byte = rx[ARRAY_SIZE(rx) - 3];
    unsigned int second_byte = rx[ARRAY_SIZE(rx) - 2];
    unsigned int third_byte = rx[ARRAY_SIZE(rx) - 1];

    if ( verbose ) {
        printf("First byte: %d\n", first_byte);
        printf("Second byte %d\n", second_byte);
        printf("Third byte %d\n", third_byte);
    }

    if ( first_byte && !chip ) {
        close(fd);
        if ( verbose ) {
            perror("Protocol error: the first byte is not 0!");
        } else {
            vexit("E");
        }
    }

    if ( second_byte > 127 ) {
        close(fd);
        if ( verbose ) {
            perror("Protocol error: the first bit of the second byte must be 0!");
        } else {
            vexit("E");
        }
    }

    unsigned int padding;

    padding = 7;

    if ( ( third_byte & padding ) != 0 ) {
        close(fd);
        if ( verbose ) {
            perror("Protocol error: the last three bit of the third byte must be 0");
        } else {
            vexit("E");
        }
    }

    signed long lettura;

    if ( chip ) {
        lettura = third_byte >> 5;
        lettura |= second_byte << 3;
        bipolarconvert = 511;
        lsb = MAX124_lsb;
    } else {
        lettura = third_byte >> 3; 
        lettura |= second_byte << 5;    
    }
    if ( !unipolar ) {
        if ( verbose ) {
                    printf("unipolar algorithm\n");
            }
        if ( lettura > bipolarconvert ) {
            lettura &= bipolarconvert;
            lettura -= bipolarconvert;
            lettura -= 1;
            if ( verbose ) {
                printf("Negative vaule");
                    }
        }   
    }


    float volt = lettura * lsb;
    if ( fullscale ) {
        volt = volt * fullscale / 4.096;
        if ( verbose ) {
                printf("Fullscale is %f\n", fullscale);
            }
    }
    if ( raw ) {
        if ( verbose ) {
            printf("Raw read: ");
        }
        printf("%d", lettura);
    } else {
        if ( verbose ) {
            printf("Analog read: ");
        }
        printf("%f", volt);
    }
    if ( newline || verbose ) {
        printf("\n");
    }

}

and now wanted to get the value of Analog Read in Python, this is my difficulty

tried through ctypes and can’t get the value of Analog Read, the code is as follows:

from ctypes import*
adder = CDLL('./raspandmax.so')# segui o exemplo na explicação do CTypes na documentação do mesmo.
valor=adder.main()
print(valor)
  • You need to compile the file with extension .c. You can run the executable that results from the previous build.

  • I have the compiled file with extension. c, now I wanted to call this file in a Python script and run it through Python, that’s what I’m not able to program

1 answer

2

Python’s ctypes module is a way of calling functions in native code - including functions written in C - from Python.

Its use is not trivial, as is often the case with other Python features (although it is not much more complicated than programming using dynamic libraries in pure C - except that if you are going to use a library that has no specific support for Python, you have to redo the function statements (the prototypes in C, usually in the files ". h") in Python using the ctypes classes and functions for this.

But in this case, not just your C program (it’s different from what you wrote: you don’t "call the file. c", you "run program code compiled from the file. c", not only is the code made to be a complete stand-alone program, with all direct functionality in the function main, as it does not return a value, nor does it have functions that return values to the caller - it prints the results in the standard output.

In this case it would make little sense to make maneuvers to call this code directly with ctypes, since the values returned by the functions in the program do not serve for anything (or main must return "0" if successful).

What you want is to capture the data that this program puts in the default output when it runs as an independent process.

Now the good news: this is well easier to do in Python than to call code using ctypes.

All you need to do is, with the desired program on PATH system - let’s say it’s called read_sensors:

import subprocess

sensor_data = subprocess.check_output("read_sensors").decode()

Done - the output of the program is all in the variable "sensor_data" and you can now use the Python functionalities to manipulate strings, as the method split and others, to separate the desired data and use them from Python.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.