Servo control

Topics (not sure which fora)
when not sure where to post, post here and mods will move it to right forum.

Moderators: leecollings, remb0

Post Reply
edwin1234
Posts: 287
Joined: Sunday 09 October 2016 20:20
Target OS: Raspberry Pi / ODroid
Domoticz version: 2021.1
Location: Nederland
Contact:

Servo control

Post by edwin1234 »

Is it possible to control a servo with domoticz?
I want to use it to open and close a "downlufter"
(A ventilation opening in a window)
Like: when heating on downlufter close,
When heating off downlufter open

How can this be done?

Thanks
User avatar
jvdz
Posts: 2336
Joined: Tuesday 30 December 2014 19:25
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.107
Location: Netherlands
Contact:

Re: Servo control

Post by jvdz »

I have 3 servo's, used for tilting my blinds, connected to the raspberry PI.
The position of the servo's is controlled by ServoBlaster on the RPi.
I use a couple of bash script files which translate the position of a dummy dimmer to the correct command for ServoBlaster.
These scripts also ensure the tilting goes smoothly in stead of a quick angle change as it would scare the hell out of everybody.

Jos
New Garbage collection scripts: https://github.com/jvanderzande/GarbageCalendar
edwin1234
Posts: 287
Joined: Sunday 09 October 2016 20:20
Target OS: Raspberry Pi / ODroid
Domoticz version: 2021.1
Location: Nederland
Contact:

Re: Servo control

Post by edwin1234 »

Thank you for your aswer
could you share the scripts?
User avatar
jvdz
Posts: 2336
Joined: Tuesday 30 December 2014 19:25
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.107
Location: Netherlands
Contact:

Re: Servo control

Post by jvdz »

edwin1234 wrote:could you share the scripts?
Sure, but guess they also need some explanation.
Let me explain the basics after which you can have a look and see how much makes sense and what needs more explanation.
Let me start with the basics:
I have 2 Dimmers defined for setting the 3 Blinds, so one controls the first blinds and the second dimmer controls the 2 other blinds.
I have 2 User variable defined which remember the current state of each dimmer, which allows me to calculate the difference after one or both dimmer are changed.
Each dimmer has these lines for action:
Knipsel.PNG
Knipsel.PNG (41.84 KiB) Viewed 2735 times
And the Blinds_Set_run.sh script contains the following code:

Code: Select all

#!/bin/bash
#--Set variables
chk=`sudo ps x | grep "Blinds_Set.sh 0" | grep -cv grep`
if  [ "$chk" = "0" ] ; then
	sh /home/pi/domoticz/scripts/Blinds_Set.sh 0 191 31 Blinds1 >> /var/tmp/blinds1.log 2>&1 &
#--else
#--	echo "$(date +%x) $(date +%X) Blinds_Set.sh is already running" >> /var/tmp/blinds.log
fi

chk=`sudo ps x | grep "Blinds_Set.sh 1" | grep -cv grep`
if  [ "$chk" = "0" ] ; then
	sh /home/pi/domoticz/scripts/Blinds_Set.sh 1 281 32 Blinds2 >> /var/tmp/blinds2.log 2>&1 &
#--else
#--	echo "$(date +%x) $(date +%X) Blinds_Set.sh is already running" >> /var/tmp/blinds.log
fi
I have chosen to use an script in between like this to be able to check whether the actual action script is already running avoiding to run it multiple times and to end the event trigger immediately avoiding "hanging"the domoticz event system while the blinds are changing their angle.
You need to update the commands in the script with the correct IDX numbers and devicenames.

The shelled Blinds_Set.sh scripts will check the current status of the dimmer and compare that with the last saved value. In case they differ the servos will be activated in small steps so they slowly change.
This is the actual action script:

Code: Select all

#!/bin/bash
#
# Script to control a Servo via an "Blinds Percentage" device in Domoticz.
#
#--Set variables
urlpre='http://192.168.?.??:8080/json.htm'
idxBlindDevice=$2
NameBlindDevice="$4"
idxSaveBlindAngle=$3
NameSaveBlindAngle="$4_current_Level"
if [ -z "$1" ] ; then
	ServoNummer="0"
else
	ServoNummer="$1"
fi
if [ -z "$5" ] ; then
	MaxOpen=0
else
	MaxOpen=$5
fi
#~ pulse traveling 900 to 2100 usec means ServoBlaster needs to send 90-210
ServoMin=90
ServoFlat=110
ServoMax=200
servostep=1
ServoCur=0
ServoNew=0
Speling=0
Direction=0
slowdown=0.03
#
# set servo level
SetServo()
{
  echo -n "$1;"
  #~ echo $ServoNummer=$1
  echo $ServoNummer=$1 > /dev/servoblaster
}
#
#~ Get current Levels and new level
echo "`date +"%x %X"` =================================================================================================================================================="
Result=`curl -s "$urlpre?type=devices&rid=$idxBlindDevice"`
BlindsMax=`echo "$Result"| /usr/local/bin/jq -r '.result[]|.MaxDimLevel'`
Blindsflat=$(((ServoMax-ServoFlat)/(ServoMax-ServoMin)*BlindsMax))
#~ echo "$urlpre?type=devices&rid=$idxBlindDevice"
BlindsNewStatus=`echo "$Result"| /usr/local/bin/jq -r '.result[]|.Status'`
ServoTotalSteps=$((ServoMax-ServoFlat))
ServoCur=`curl -s "$urlpre?type=command&param=getuservariable&idx=$idxSaveBlindAngle"| /usr/local/bin/jq -r '.result[]|.Value'`
if [ $ServoCur -lt $ServoMin ]; then
	ServoCur=$ServoMin
fi
if [ $ServoCur -gt $ServoMax ]; then
	ServoCur=$ServoMax
fi
##
if [ "$BlindsNewStatus" = "Closed" ]; then
	BlindsNewAngle=$BlindsMax
	ServoNew=$ServoMax
elif [ "$BlindsNewStatus" = "Open" ]; then
	BlindsNewAngle=$Blindsflat
	ServoNew=$ServoFlat
else
	BlindsNewAngle=`echo "$Result"| /usr/local/bin/jq -r '.result[]|.LevelInt'`
	ServoNew=$((BlindsNewAngle*ServoTotalSteps/BlindsMax+ServoFlat))
fi

## Opion to open the blinds Maximal
if [ $MaxOpen -eq 1 ]; then
	ServoNew=$ServoMin
fi

#~ BlindsMax=`curl -s "$urlpre?type=devices&rid=$idxBlindDevice"| /usr/local/bin/jq -r '.result[]|.MaxDimLevel'`
#~ BlindsNewAngle=`curl -s "$urlpre?type=devices&rid=$idxBlindDevice"| /usr/local/bin/jq -r '.result[]|.LevelInt'`
#~ BlindsCurAngle=`curl -s "$urlpre?type=command&param=getuservariable&idx=$idxSaveBlindAngle"| /usr/local/bin/jq -r '.result[]|.Value'`
echo -n "`date +"%x %X"` Start changing Blinds angle with Servo $ServoNummer  Name $NameBlindDevice"
echo "   ServoCur=$ServoCur    ServoNew=$ServoNew   BlindsNewStatus=$BlindsNewStatus   BlindsNewAngle=$BlindsNewAngle"
if [ $ServoNew -eq $ServoCur ]; then
	echo "`date +"%x %X"` Nothing to do."
else
	#
	#Calculate the Servo angle
	# set the direction
	if [ $ServoNew -gt $((ServoCur+servostep-1)) ]; then
		Direction=1
	fi
	echo "`date +"%x %X"` ServoTotalSteps:$ServoTotalSteps    ServoCur=$ServoCur      ServoNew=$ServoNew   Direction=$Direction"

	## move the servo a bit at the time to avoid a rapic change of angle
	cnt=1
	echo -n "`date +"%x %X"` "
	while true; do
		if [ $ServoNew -gt $((ServoCur+servostep-1)) ]; then
			ServoCur=$((ServoCur+servostep))
		elif [ $ServoNew -lt $((ServoCur-servostep+1)) ]; then
			ServoCur=$((ServoCur-servostep))
		else
			break
		fi
		SetServo $ServoCur
		sleep $slowdown
	done
	# Update the User variable to save the last set angle
	curl -s "$urlpre?type=command&param=updateuservariable&idx=$idxSaveBlindAngle&vname=$NameSaveBlindAngle&vtype=0&vvalue=$ServoNew"| grep OK > /dev/null
	if [ $? -eq 0 ] ; then
		echo " "
		echo "`date +"%x %X"` Done"
		#~ echo "`date +"%x %X"` done updating $NameSaveBlindAngle to BlindsNewAngle=$BlindsNewAngle   percentage=$((($ServoCur-ServoMin)*100/ServoTotalSteps))"
	else
		echo " "
		echo "`date +"%x %X"` Done, but error updating $NameSaveBlindAngle to $ServoNew   : ServoCur=$ServoCur  percentage=$((($ServoCur-ServoMin)*100/ServoTotalSteps))"
	fi
	#~ sleep 0.3
	#~ echo -n "`date +"%x %X"` done: Stop Servo by sending: "
	#~ SetServo 0
	#~ echo "Done."
	# set slider at corret level when Open or Close was selected and option isn't maxopen
	if [ $MaxOpen -ne 1 ]; then
		if [ "$BlindsNewStatus" = "Closed" ]; then
			echo "`date +"%x %X"` Closed set so change level to $BlindsMax."
			Result=`curl -s "$urlpre?type=command&param=switchlight&idx=$idxBlindDevice&switchcmd=Set%20Level&level=$BlindsMax"`
			#~ echo "$Result"
		elif [ "$BlindsNewStatus" = "Open" ]; then
			echo "`date +"%x %X"` Open set so change level to 0."
			Result=`curl -s "$urlpre?type=command&param=switchlight&idx=$idxBlindDevice&switchcmd=Off&level=0"`
		fi
	fi
fi
Make sure you update these variables with the appropriate information for your servo's:
#~ pulse traveling 900 to 2100 usec means ServoBlaster needs to send 90-210
ServoMin=90 #~ minimal angle value
ServoFlat=110 #~ angle value for the position the blinds are exactly flat (open)
ServoMax=200 #~ maximum angle value
servostep=1 #~ define the change for each step
slowdown=0.03 #~ define the "sleep" between each step

Hope it all makes some sense, but ask away when you have questions. :)
Jos
New Garbage collection scripts: https://github.com/jvanderzande/GarbageCalendar
edwin1234
Posts: 287
Joined: Sunday 09 October 2016 20:20
Target OS: Raspberry Pi / ODroid
Domoticz version: 2021.1
Location: Nederland
Contact:

Re: Servo control

Post by edwin1234 »

Thank u very much for your scripts and info,
i let you know if i have questions.
mbunds
Posts: 1
Joined: Tuesday 30 April 2019 21:35
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Servo control

Post by mbunds »

JVDZ - Sure, but guess they also need some explanation...
Thank you for sharing this information. I know it was a while ago, but it was very helpful. I registered here just to tell you "thanks"!
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest