04-23-2019, 12:32 PM
Hello!
Wrote F.A.Q. on request Drone7
To use an analog potentiometer as a volume control with a raspberry pi you will need:
- ADC, I used ADS1115 link
- analog POT, I used the simplest link
We increase or decrease the system volume using the command-line program
Install the ADS1115 ADC in the following order (source - link):
1. Enable I2C on the Raspberry Pi using raspi-config
Run
and follow the prompts to install i2c support for the ARM core and linux kernel
Go to Interfacing Options, then I2C -> Enable! –> Yes
Once this is all done, reboot!
2. Testing i2c
This shows that I2C address ADC
3. Connect the ADC to the Pi as follows:
- ADS1x15 VDD to Raspberry Pi 3.3V
- ADS1x15 GND to Raspberry Pi GND
- ADS1x15 SCL to Raspberry Pi SCL
- ADS1x15 SDA to Raspberry Pi SDA
4. Source Install
To install from the source on Github connect to a terminal on the Raspberry Pi and run the following commands:
5. Connecting an analog potentiometer
It goes according to the following scheme:
Left leg - GND
Central leg - A1 ADS1115
Right leg - VCC 3.3 v
6. Check potentiometer connection
Go to the folder examples:
run the simpletest.py
When rotating the potentiometer knob, the values of channel 1 should change. Check that there are no negative values in the leftmost position (readings 0-2). Otherwise, check the quality of connections, it is better to collect on the soldering.
Write down the value in the extreme right position (required to correct the code). I have - 26274
Now set the code for the operation of the potentiometer, the manual is taken as the basis - link
First, make sure amixer is present and install it if it isn’t.
You might not have Python 3; if which python3 turns up nothing, try this:
in home / pi, create a python file with any name (in my case it is volknob.py) and copy this code into it
In the code variables are the following values:
VOLUME_MIN = 0
VOLUME_MAX = 100
VOLUME_INCREMENT = 1
# Audio device name, e.g. 'PCM’, 'Master' or your sound card. Find with: amixer scontrols
DEVICE_NAME = 'PCM'
# convert trim pot read into 0-100 volume level
set_volume = int(round(trim_pot / 262.74)) – specify the value from clause 6/100
Next we create an autorun service (described on the author’s code page) and enjoy.
P.s. translation via google, code copied from Putty, could be wrong
Wrote F.A.Q. on request Drone7
To use an analog potentiometer as a volume control with a raspberry pi you will need:
- ADC, I used ADS1115 link
- analog POT, I used the simplest link
We increase or decrease the system volume using the command-line program
Code:
amixer
1. Enable I2C on the Raspberry Pi using raspi-config
Code:
sudo apt-get install -y python-smbus
sudo apt-get install -y i2c-tools
Code:
sudo raspi-config
Go to Interfacing Options, then I2C -> Enable! –> Yes
Once this is all done, reboot!
Code:
sudo reboot
2. Testing i2c
Code:
sudo i2cdetect -y 1
3. Connect the ADC to the Pi as follows:
- ADS1x15 VDD to Raspberry Pi 3.3V
- ADS1x15 GND to Raspberry Pi GND
- ADS1x15 SCL to Raspberry Pi SCL
- ADS1x15 SDA to Raspberry Pi SDA
4. Source Install
To install from the source on Github connect to a terminal on the Raspberry Pi and run the following commands:
Code:
sudo apt-get update
sudo apt-get install build-essential python-dev python-smbus git
cd ~
git clone https://github.com/adafruit/Adafruit_Python_ADS1x15.git
cd Adafruit_Python_ADS1x15
sudo python setup.py install
5. Connecting an analog potentiometer
It goes according to the following scheme:
Left leg - GND
Central leg - A1 ADS1115
Right leg - VCC 3.3 v
6. Check potentiometer connection
Go to the folder examples:
Code:
cd ~/Adafruit_Python_ADS1x15/examples
Code:
sudo python simpletest.py
Write down the value in the extreme right position (required to correct the code). I have - 26274
Now set the code for the operation of the potentiometer, the manual is taken as the basis - link
First, make sure amixer is present and install it if it isn’t.
Code:
which amixer || sudo apt-get install alsa-utils
You might not have Python 3; if which python3 turns up nothing, try this:
Code:
sudo apt-get install python3
Code:
#!/usr/bin/python
# coding=utf-8
#############################################################################################################
### Copyright by Joy-IT
### Published under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
### Commercial use only after permission is requested and granted
### Programme traduit par Go tronic
###
### Single Analog Sensor - Raspberry Pi Python Code Example
###
#############################################################################################################
# Ce code utilise les librairies Python ADS1115 et I2C pour la Raspberry Pi
# Ces librairies sont publiées sous licence BSD sur le lien ci-dessous
# [https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code]
import Adafruit_ADS1x15
from time import sleep
# Les modules nécessaires sont importés et mis en place
import time, signal, os, math
import logging
import signal
import subprocess
import sys
# Les variables utilisées sont initialisées
delayTime = 0.2
voltageMax = 3300
# valeur de tension maximale possible à l'entrée du convertisseur ADC
# attribution d'adresse ADS1x15 ADC
ADS1015 = 0x00 # 12-bit ADC
ADS1115 = 0x01 # 16-bit ADC
# Choix du gain
gain = 1 # +/- 4.096V
# gain = 2048 # +/- 2.048V
# gain = 1024 # +/- 1.024V
# gain = 512 # +/- 0.512V
# gain = 256 # +/- 0.256V
# Choix de la fréquence d'échantillonnage ADC (SampleRate)
# sps = 8 # 8 échantillons par seconde
# sps = 16 # 16 échantillons par seconde
# sps = 32 # 32 échantillons par seconde
# sps = 64 # 64 échantillons par seconde
# sps = 128 # 128 échantillons par seconde
sps = 250 # 250 échantillons par seconde
# sps = 860 # 860 échantillons par seconde
# choix du canal ADC (1-4)
# adc_channel = 0 # Channel 0
adc_channel = 1 # Channel 1
# adc_channel = 2 # Channel 2
# adc_channel = 3 # Channel 3
# initialisation du convertisseur
adc = Adafruit_ADS1x15.ADS1115()
#############################################################################################################
# ########
# boucle de programme principale
# ########
# Le programme mesure la tension à l'aide du convertisseur ADS1115.
# Il calcule la résistance de la LDR et les transmet à la console.
logger = logging.getLogger(__name__)
# logging
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)-15s - %(message)s'
)
# SETTINGS
# ========
DEBUG = True
# The minimum and maximum volumes, as percentages.
#
# The default max is less than 100 to prevent distortion. The default min is
# greater than zero because if your system is like mine, sound gets
# completely inaudible _long_ before 0%. If you've got a hardware amp or
# serious speakers or something, your results will vary.
VOLUME_MIN = 0
VOLUME_MAX = 100
# The amount you want one click of the knob to increase or decrease the
# volume. I don't think that non-integer values work here, but you're welcome
# to try.
VOLUME_INCREMENT = 1
# Audio device name, e.g. 'PCM' or 'Master'. Find with: amixer scontrols
DEVICE_NAME = 'PCM'
# (END SETTINGS)
#
def debug(str):
if not DEBUG:
return
logger.debug(str)
class RotaryEncoder(object):
"""
A class to decode mechanical rotary encoder pulses.
"""
def __init__(self, channel, tolerance=5):
self.adc = Adafruit_ADS1x15.ADS1115()
self.volume = Volume()
self.channel = adc_channel
# to keep from being jittery we'll only change
# volume when the pot has moved more than 5 'counts'
self.tolerance = tolerance
# this keeps track of the last potentiometer value
self.last_read = 0
def destroy(self):
debug('Destroying...')
def read(self):
# we'll assume that the pot didn't move
trim_pot_changed = False
# read the analog pin
trim_pot = self.adc.read_adc(self.channel, gain, sps)
# how much has it changed since the last read?
pot_adjust = abs(trim_pot - self.last_read)
if pot_adjust > self.tolerance:
trim_pot_changed = True
if trim_pot_changed:
# convert trim pot read into 0-100 volume level
set_volume = int(round(trim_pot / 262.74))
self.volume.set_volume(set_volume)
# save the potentiometer reading for the next loop
self.last_read = trim_pot
class VolumeError(Exception):
pass
class Volume(object):
"""
A wrapper API for interacting with the volume settings on the RPi.
"""
MIN = VOLUME_MIN
MAX = VOLUME_MAX
INCREMENT = VOLUME_INCREMENT
def __init__(self):
# Set an initial value for last_volume in case we're muted when we start.
self.last_volume = self.MIN
self._sync()
def up(self):
"""
Increases the volume by one increment.
"""
return self.change(self.INCREMENT)
def down(self):
"""
Decreases the volume by one increment.
"""
return self.change(-self.INCREMENT)
def change(self, delta):
v = self.volume + delta
v = self._constrain(v)
return self.set_volume(v)
def set_volume(self, v):
"""
Sets volume to a specific value.
"""
self.volume = self._constrain(v)
debug("set volume: {}".format(self.volume))
output = self.amixer("set -M '{}' unmute {}%".format(DEVICE_NAME, v))
self._sync(output)
return self.volume
def toggle(self):
"""
Toggles muting between on and off.
"""
if self.is_muted:
output = self.amixer("set -M '{}' unmute".format(DEVICE_NAME))
else:
# We're about to mute ourselves, so we should remember the last volume
# value we had because we'll want to restore it later.
self.last_volume = self.volume
output = self.amixer("set -M '{}' mute".format(DEVICE_NAME))
self._sync(output)
if not self.is_muted:
# If we just unmuted ourselves, we should restore whatever volume we
# had previously.
self.set_volume(self.last_volume)
return self.is_muted
def status(self):
if self.is_muted:
return "{}% (muted)".format(self.volume)
return "{}%".format(self.volume)
# Read the output of `amixer` to get the system volume and mute state.
#
# This is designed not to do much work because it'll get called with every
# click of the knob in either direction, which is why we're doing simple
# string scanning and not regular expressions.
def _sync(self, output=None):
if output is None:
output = self.amixer("get -M '{}'".format(DEVICE_NAME))
lines = output.readlines()
if DEBUG:
strings = [line.decode('utf8') for line in lines]
debug("OUTPUT:")
debug("".join(strings))
last = lines[-1].decode('utf-8')
# The last line of output will have two values in square brackets. The
# first will be the volume (e.g., "[95%]") and the second will be the
# mute state ("[off]" or "[on]").
i1 = last.rindex('[') + 1
i2 = last.rindex(']')
self.is_muted = last[i1:i2] == 'off'
i1 = last.index('[') + 1
i2 = last.index('%')
# In between these two will be the percentage value.
pct = last[i1:i2]
self.volume = int(pct)
# Ensures the volume value is between our minimum and maximum.
def _constrain(self, v):
if v < self.MIN:
return self.MIN
if v > self.MAX:
return self.MAX
return v
def amixer(self, cmd):
p = subprocess.Popen("amixer {}".format(cmd), shell=True, stdout=subprocess.PIPE)
code = p.wait()
if code != 0:
raise VolumeError("Unknown error: {}".format(code))
sys.exit(0)
return p.stdout
if __name__ == "__main__":
def on_exit(a, b):
debug("Exiting...")
encoder.destroy()
sys.exit(0)
encoder = RotaryEncoder( adc_channel)
signal.signal(signal.SIGINT, on_exit)
debug("Initial volume: {}".format(encoder.volume.volume))
while True:
encoder.read()
# hang out and do nothing for a half second
time.sleep(0.5)
VOLUME_MIN = 0
VOLUME_MAX = 100
VOLUME_INCREMENT = 1
# Audio device name, e.g. 'PCM’, 'Master' or your sound card. Find with: amixer scontrols
DEVICE_NAME = 'PCM'
# convert trim pot read into 0-100 volume level
set_volume = int(round(trim_pot / 262.74)) – specify the value from clause 6/100
Next we create an autorun service (described on the author’s code page) and enjoy.
P.s. translation via google, code copied from Putty, could be wrong