0

I'm fairly new to bash scripting and linux in general. I'm trying to send a series of rapid commands to pressure regulator (half a second apart), which I normally do so with simple square pulse using bash scripts. However I can't seem to get the syntax correct for a sine wave shaped pulse instead. I couldn't find a way to use an actual sine function, but a series of small discrete steps would work just as well.

Here's my script:

#!/bin/bash

Pmax="90"
Pmin="10"
Rcor="7.91"  #This converts the pressure setting into the devices scaled range.
declare -a Sinewave20=(0 0.309 0.588 0.809  0.951  1  0.951  0.809  0.580 0.309 0 -0.309 -0.588 -0.809 -0.951 -1 -0.951 -0.809 -0.588 -0.309)
Amplitude=$(( $Pmax-$Pmin ))
Offset=$(( $Pmin+$Amplitude/2  ))

# 6 cycles of Sinewave20 corresponds to 1 min of .1 hz sine wave
for i in {0..6}
do
        # Let's send the commands for a 20 pt sine wave
        for x in "${!Sinewave20[@]}";
        do
                Value=$(( $Amplitude*$Rcor*$Sinewave20[x]+{Offset*$Rcor ))

                echo -e "SET ${Value}\r"  > /dev/ttyUSB1
                sleep 0.5
        done
done

This results in the following error msg:

line 18: 80*7.91*0[x]+{Offset*7.91: syntax error: invalid arithmetic operator (error token is ".91*0[x]+{Offset*7.91")

I've tried various ways of writing it but haven't found one that works. The command to change the pressure is simply:

echo -e "SET 100\r" > /dev/ttyUSB1

3 Answers3

3

Bash arithmetic is limited to integers.

Consider using a scripting engine that has built-in support for floating point numbers. Either the light weight awk or bc, or one of the full languages: Python, Perl, etc.

See: How do I use floating-point division in bash? and https://unix.stackexchange.com/questions/40786/how-to-do-integer-float-calculations-in-bash-or-other-languages-frameworks/40787#40787

dash-o
  • 13,723
  • 1
  • 10
  • 37
  • Actually, just knowing that Bash is limited to integer math, told me exactly how to get around the issue I was having. I just calculated all the points in a spreadsheet, made sure they were integer values, put them into an array to be read by the Bash script and echo'd to the device. That worked, it's not very flexible, but it got around the issue. Today, a co-work gave me a python script that I can start adapting. Thanks for your timely advice! – Daniel Max Sherman Dec 06 '19 at 23:13
  • @DanielMaxSherman I've noticed few typos in the awk solution, which prevented it from working. Posting slightly modified script, in case you want to use the simpler awk instead of python. Whatever works ... – dash-o Dec 07 '19 at 04:42
0

Would you try the substitution with awk:

Pmax="90"
Pmin="10"
Rcor="7.91"

awk -v Pmax="$Pmax" -v Pmin="$Pmin" -v Rcor="$Rcor" '
BEGIN {
    PI = atan2(0, -1)
    Amplitude = Pmax - Pmin
    Offset = Pmin + Amplitude / 2
    for (i = 0; i <= 6; i++) {
        for (j = 0; j < 20; j++) {
            Value = (Amplitude * sin(j / 10 * PI) + Offset) * Rcor
            printf("SET %f\r\n", Value) > /dev/ttyUSB1
            system("sleep 0.5")
        }
    }
}'

Hope this helps.

tshiono
  • 21,248
  • 2
  • 14
  • 22
  • I tried this today, and while it didn't give an error, it didn't work. I'm not familiar enough with awk statements to de-bug it. For the reason listed above, I'm going to give the best answer to the comment above. – Daniel Max Sherman Dec 06 '19 at 23:10
0

This is modified version of tshiono awk script, addressing few typos (the /dev/... must be quoted, ...), technical problems (device must be closed on every iteration, ...), and slightly simplified.

To TEST the script: bash script.sh, it will show the values that will be sent (no delay)

To RUN the script: bash script.sh /dev/ttyUSB1.

File: script.sh

#! /bin/bash
awk -v Device="$1" '
BEGIN {
    Pmax=90
    Pmin=10
    Rcor=7.91
    PI = atan2(0, -1)
    Amplitude = Pmax - Pmin
    Offset = Pmin + Amplitude / 2
    for (i = 0; i <= 6; i++) {
        for (j = 0; j < 20; j++) {
            Value = (Amplitude * sin(j / 10 * PI) + Offset) * Rcor
            printf "Sending: SET %f\r\n", Value > "/dev/stderr"
            if ( Device ) {
                printf "SET %f\r\n", Value > Device
                close(Device)
                system("sleep 0.5")
            }  
        }
    }
}'
dash-o
  • 13,723
  • 1
  • 10
  • 37