+#!/bin/bash
+
+#==BEGIN function definition==
+yell() { echo "$0: $*" >&2; } # print script path and all args to stderr
+die() { yell "$*"; exit 111; } # same as yell() but non-zero exit status
+try() { "$@" || die "cannot $*"; } # runs args as command, reports args if command fails
+update_pi() {
+ # Desc: Calculates control variable (CV) given setpoint (SP) and
+ # process variable (PV). Uses proportional integral (PI)
+ # control.
+ # Usage: update_pi arg1 arg2 arg3 arg4 arg5
+ # Version: 0.0.1
+ # Input: arg1: path_loop_name (control loop name path)
+ # arg2: var_pv (process variable)
+ # arg3: var_sp (set point)
+ # arg4: tune_p (proportional tuning factor)
+ # arg5: tune_i (integral tuning factor)
+ # Output: stdout: var_cv (control variable)
+ # file: path_var_pv
+ # file: path_var_sp
+ # file: path_tune_p
+ # file: path_tune_i
+ # file: path_sum (saves updated sum state)
+ # Example: update_pi /dev/shm/DC1.AC 1.0 3.0 2.0 3.0
+ # Depends: bc, gnu coreutils 8.30, yell(), try()
+ local var_sp var_pv var_cv;
+ local tune_p tune_i;
+ local term_p term_i;
+ local error sum;
+ local path_sum path_var_sp path_var_pv path_tune_p path_tune_i;
+
+ path_loop_name="$1";
+
+ path_var_pv="$path_loop_name".pv
+ var_pv="$2"; # read provided process variable
+
+ path_var_sp="$path_loop_name".sp
+ if [[ -f "$path_var_sp" ]]; then
+ var_sp="$(cat "$path_var_sp" | head -n1)";
+ else
+ var_sp="$3";
+ fi;
+
+ path_tune_p="$path_loop_name".tune_p
+ if [[ -f "$path_tune_p" ]]; then
+ tune_p="$(cat "$path_tune_p" | head -n1)";
+ else
+ tune_p="$4";
+ fi;
+
+ path_tune_i="$path_loop_name".tune_i
+ if [[ -f "$path_tune_i" ]]; then
+ tune_i="$(cat "$path_tune_i" | head -n1)";
+ else
+ tune_i="$5";
+ fi;
+
+ path_sum="$path_loop_name".sum
+ if [[ -f "$path_sum" ]]; then
+ sum="$(cat "$path_sum" | head -n1)";
+ else
+ sum=0;
+ fi;
+
+ #yell "DEBUG:path_loop_name:$path_loop_name";
+ #yell "DEBUG:var_pv:$var_pv";
+ #yell "DEBUG:var_sp:$var_sp";
+ #yell "DEBUG:tune_p:$tune_p";
+ #yell "DEBUG:tune_i:$tune_i";
+
+ error="$(try echo "$var_sp - $var_pv" | bc -l)";
+ #yell "DEBUG:error:$error";
+ sum="$(try echo "$sum + $error" | bc -l)";
+ #yell "DEBUG:sum:$sum";
+ term_p="$(try echo "$tune_p * $error" | bc -l)";
+ #yell "DEBUG:term_p:$term_p";
+ term_i="$(try echo "$tune_i * $sum" | bc -l)";
+ #yell "DEBUG:term_i:$term_i";
+ var_cv="$(try echo "$term_p + $term_i" | bc -l)";
+ #yell "DEBUG:var_cv:$var_cv";
+
+ # Write variables to memory
+ echo "$sum" > "$path_sum";
+ echo "$var_sp" > "$path_var_sp";
+ echo "$var_pv" > "$path_var_pv";
+ echo "$tune_p" > "$path_tune_p";
+ echo "$tune_i" > "$path_tune_i";
+
+ # Output control variable to stdout
+ echo "$var_cv";
+
+ #yell "DEBUG:=============END_ROUND===============";
+}
+#==END function definition==
+
+#==BEGIN Example code==
+path_loop_name="/tmp/DC1.AC";
+var_pv=1.0;
+var_sp=2.0;
+tune_p=1.0;
+tune_i=0.1;
+try rm "$path_loop_name"*
+
+var_pv=4.0;
+output="$(update_pi "$path_loop_name" "$var_pv" "$var_sp" "$tune_p" "$tune_i" | tail -n1)";
+yell "DEBUG:sum:$(cat "$path_loop_name".sum | head -n1)";
+yell "DEBUG:output:$output";
+var_pv=4.0;
+output="$(update_pi "$path_loop_name" "$var_pv" "$var_sp" "$tune_p" "$tune_i" | tail -n1)";
+yell "DEBUG:sum:$(cat "$path_loop_name".sum | head -n1)";
+yell "DEBUG:output:$output";
+var_pv=4.0;
+output="$(update_pi "$path_loop_name" "$var_pv" "$var_sp" "$tune_p" "$tune_i" | tail -n1)";
+yell "DEBUG:sum:$(cat "$path_loop_name".sum | head -n1)";
+yell "DEBUG:output:$output";
+var_pv=4.0;
+output="$(update_pi "$path_loop_name" "$var_pv" "$var_sp" "$tune_p" "$tune_i" | tail -n1)";
+yell "DEBUG:sum:$(cat "$path_loop_name".sum | head -n1)";
+yell "DEBUG:output:$output";
+var_pv=4.0;
+output="$(update_pi "$path_loop_name" "$var_pv" "$var_sp" "$tune_p" "$tune_i" | tail -n1)";
+yell "DEBUG:sum:$(cat "$path_loop_name".sum | head -n1)";
+yell "DEBUG:output:$output";
+var_pv=1.0;
+output="$(update_pi "$path_loop_name" "$var_pv" "$var_sp" "$tune_p" "$tune_i" | tail -n1)";
+yell "DEBUG:sum:$(cat "$path_loop_name".sum | head -n1)";
+yell "DEBUG:output:$output";
+var_pv=1.0;
+output="$(update_pi "$path_loop_name" "$var_pv" "$var_sp" "$tune_p" "$tune_i" | tail -n1)";
+yell "DEBUG:sum:$(cat "$path_loop_name".sum | head -n1)";
+yell "DEBUG:output:$output";
+var_pv=1.0;
+output="$(update_pi "$path_loop_name" "$var_pv" "$var_sp" "$tune_p" "$tune_i" | tail -n1)";
+yell "DEBUG:sum:$(cat "$path_loop_name".sum | head -n1)";
+yell "DEBUG:output:$output";
+var_pv=1.0;
+output="$(update_pi "$path_loop_name" "$var_pv" "$var_sp" "$tune_p" "$tune_i" | tail -n1)";
+yell "DEBUG:sum:$(cat "$path_loop_name".sum | head -n1)";
+yell "DEBUG:output:$output";
+#==END Example code==
+
+# Author: Steven Baltakatei Sandoval
+# License: GPLv3+