jelly_p
Posts: 9
Joined: Wed Feb 26, 2014 11:22 pm

Push buttons different resistance

Wed Feb 26, 2014 11:29 pm

Hi

I have taken apart an old Radio/CD system and I am planning to replace the broken CD player with a PI.

The CD buttons have a 3 wire connection as follows

1 - Common
2 - Play Button
3 - Other Buttons

The other buttons adjust the resistance between pins 1 and 3 as follows:

Program: 22K
Repeat: 12.4K
Skip - : 7.7K
Skip + : 4.4K
Stop: 1.7K

What I would like to do is break this out so that I can read which button was pressed using the GPIO pins.

Any help would be gratefully received.

User avatar
mahjongg
Forum Moderator
Forum Moderator
Posts: 13092
Joined: Sun Mar 11, 2012 12:19 am
Location: South Holland, The Netherlands

Re: Push buttons different resistance

Wed Feb 26, 2014 11:39 pm

there are many possible solutions for the multiple buttons on a wire solution. The least hardware intensive would be timing how much time it takes to charge a capacitor through the variable resistor. you need a single GPIO for that, switch it to output to discharge the capacitor connected between GPIO and GND, then switch to input and measure the time it takes to charge the capacitor through the variable resistor connected to 3V3, until the inputs reads a "1" instead of a "0".

A more traditional approach would be to use a quad comparator that senses the voltage of a resistor dived of which one branch is the variable resistance, and another a resistor of fixed voltage. With a LM339 you can set up four "trip points", and connect them to 4 gpio inputs.

jelly_p
Posts: 9
Joined: Wed Feb 26, 2014 11:22 pm

Re: Push buttons different resistance

Wed Feb 26, 2014 11:44 pm

Thanks Mahjongg,

I saw the capacitor option, but was not sure how I would code it - as you need to start the process when a button is pressed.

User avatar
FLYFISH TECHNOLOGIES
Posts: 1750
Joined: Thu Oct 03, 2013 7:48 am
Location: Ljubljana, Slovenia
Contact: Website

Re: Push buttons different resistance

Wed Feb 26, 2014 11:45 pm

Hi,
jelly_p wrote:Program: 22K
Repeat: 12.4K...
What I would like to do is break this out so that I can read which button was pressed using the GPIO pins.
If you expect some mechanics issues when breaking out the buttons, you should consider using unmodified buttons and read clicks with A/D converter instead.


Best wishes, Ivan Zilic.
Running out of GPIO pins and/or need to read analog values?
Solution: http://www.flyfish-tech.com/FF32

boyoh
Posts: 1468
Joined: Fri Nov 23, 2012 3:30 pm
Location: Selby. North Yorkshire .UK

Re: Push buttons different resistance

Thu Feb 27, 2014 9:37 am

jelly_p wrote:Hi

I have taken apart an old Radio/CD system and I am planning to replace the broken CD player with a PI.

The CD buttons have a 3 wire connection as follows

1 - Common
2 - Play Button
3 - Other Buttons

The other buttons adjust the resistance between pins 1 and 3 as follows:

Program: 22K
Repeat: 12.4K
Skip - : 7.7K
Skip + : 4.4K
Stop: 1.7K

What I would like to do is break this out so that I can read which button was pressed using the GPIO pins.

Any help would be gratefully received.
A better understanding of you project ,and what you want to do
If you posted a diagram of the button's lay out and resistor
Connections. This involves some electronics, then my be
A circuit could be designed , on how to communicate
With the Pi's GPIO in/puts & out/puts.
BoyOh ( Selby, North Yorkshire.UK)
Some Times Right Some Times Wrong

PiGraham
Posts: 3932
Joined: Fri Jun 07, 2013 12:37 pm
Location: Waterlooville

Re: Push buttons different resistance

Thu Feb 27, 2014 10:15 am

[

You could perhaps remove the resistors and wire GPIOs to the contacts.

You could wire the switched resistance into a an oscillator circuit (e.g. 555 timer) and measure pulse width with one GPIO in edge mode.

You could, as suggested above, connect a capacitor and continuously toggle a GPIO to output low (A microseconds) then switch to input edge triggered (Measure B microseconds). Keep that running all the time, monitoring the time between reset low and input high.
Assuming an input high threshold on GPIO in of 2v.
Ignoring input impedance, capacitor effective series resistance (ESR),

Connect a 1uF capacitor in series with 'Other buttons' and 'common' to 3.3v.
Connect a GPIO to the junction between 'Other buttons' and the capacitor.
Tau = R*C, the time it takes an ideal capcitance to charge from zero to 63% of the voltage applied across R-C.
64% of 3.3V is 2V, somewhere in the region of our input threshold voltage.
In your software:

configure the GPIO pin as output low.
Set a timer of 20ms
When the timer expires:
Record the time
Reconfigure the GPIO as input with no pullup/down, rising edge callback

After approx R*C seconds the callback will fire
In the callback:
record the time
Calc the time interval between releasing the reset (low) state and input going high.
re-configure the GPIO as output low.
Set a timer of 20ms

In your main code monitor the calculated time.

The time interval should be approximately equal to the resistance (in k) as milliseconds.
Tau (seconds) = R (ohms) * C (Farrads)
Tau (ms) = R(kOhm) * C (uF)

This timing will not be exact, because we made simplifying assumptions, but you can measure what the times are and map them to button states.

jelly_p
Posts: 9
Joined: Wed Feb 26, 2014 11:22 pm

Re: Push buttons different resistance

Thu Feb 27, 2014 11:02 am

Thanks guys - certainly food for thought - my idea was a chain of resistors with a connection to the gpio pin at various points.

Depending on the button that is pressed the magic 2V threshold will be at different parts of the resistor chain.

but I might try the capacitor route.

User avatar
mahjongg
Forum Moderator
Forum Moderator
Posts: 13092
Joined: Sun Mar 11, 2012 12:19 am
Location: South Holland, The Netherlands

Re: Push buttons different resistance

Sun Mar 02, 2014 2:11 pm

problem is, the magic threshold isn't well defined, it might be 1.8V for one PI/GPIO and 2.2V for another. At least with the RC trick you can tweak the software to fix the relative thresholds, while the hardware level is fixed.

jelly_p
Posts: 9
Joined: Wed Feb 26, 2014 11:22 pm

Re: Push buttons different resistance

Mon Mar 03, 2014 9:53 am

Well - I have gout something working.

I used the capacitor option as outlined here:

http://www.raspberrypi-spy.co.uk/2012/0 ... -gpio-pin/

Then I was able to use the python code in that blog page to read the values for each button :D

I then used the 1 button audiobook player code on a volumio build and added some extra code to read my function buttons

http://blogs.fsfe.org/clemens/2012/10/3 ... ok-player/

I will post my code when I get the chance.

jelly_p
Posts: 9
Joined: Wed Feb 26, 2014 11:22 pm

Re: Push buttons different resistance

Thu Mar 06, 2014 9:08 pm

So here is my current code - based on the one button audiobook player code


Code: Select all

pi@volumio:/var/tmp$ cat myradio.py
#!/usr/bin/env python
# Copyright (C) 2012 Michael Clemens
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import RPi.GPIO as GPIO
import os
import pyudev
import time

from mpd import (MPDClient, CommandError)
from socket import error as SocketError
from time import sleep

# Configure MPD connection settings
HOST = 'localhost'
PORT = '6600'
CON_ID = {'host':HOST, 'port':PORT}

# Configure IO ports
PLAYBTN = 17
BUTTONS = 4
LED = 24
GPIO.setmode(GPIO.BCM)
GPIO.setup(PLAYBTN, GPIO.IN)
GPIO.setup(LED, GPIO.OUT)
# Discharge capacitor
GPIO.setup(BUTTONS, GPIO.OUT)
GPIO.output(BUTTONS, GPIO.LOW)
time.sleep(0.1)

GPIO.setup(BUTTONS, GPIO.IN)


## Some functions
def mpdConnect(client, con_id):
        """
Simple wrapper to connect MPD.
"""
        try:
                client.connect(**con_id)
        except SocketError:
                return False
        return True

def loadMusic(client, con_id, device):
        os.system("mount "+device+" /music/usb")
        os.system("/etc/init.d/mpd stop")
        os.system("rm /music/mp3/*")
        os.system("cp /music/usb/* /music/mp3/")
        os.system("umount /music/usb")
        os.system("rm /music/mpd/tag_cache")
        os.system("/etc/init.d/mpd start")
        os.system("mpc clear")
        os.system("mpc ls | mpc add")
        os.system("/etc/init.d/mpd restart")

def flashLED(speed, time):
        for x in range(0, time):
                GPIO.output(LED, GPIO.LOW)
                sleep(speed)
                GPIO.output(LED, GPIO.HIGH)
                sleep(speed)

def updateLED(client):
        # adjust LED to actual state
        if client.status()["state"] == "play":
                GPIO.output(LED, GPIO.LOW)
        else:
                GPIO.output(LED, GPIO.HIGH)

def checkForUSBDevice(name):
        res = ""
        context = pyudev.Context()
        for device in context.list_devices(subsystem='block', DEVTYPE='partition'):
                if device.get('ID_FS_LABEL') == name:
                        res = device.device_node
        return res

# Define function to measure charge time
def RCtime (PiPin):
  measurement = 0
  # Discharge capacitor
  GPIO.setup(BUTTONS, GPIO.OUT)
  GPIO.output(BUTTONS, GPIO.LOW)
  time.sleep(0.05)

  GPIO.setup(BUTTONS, GPIO.IN)
  # Count loops until voltage across
  # capacitor reads high on GPIO
  while (GPIO.input(PiPin) == GPIO.LOW):
    measurement += 1

  return measurement

def main():
        ## MPD object instance
        client = MPDClient()
        mpdConnect(client, CON_ID)

        status = client.status()
        print status

        timebuttonisstillpressed = 0

        flashLED(0.1, 5)
        updateLED(client)

        while True:
                #device = checkForUSBDevice("1GB") # 1GB is the name of my thumb drive
                #if device != "":
                        ## USB thumb drive has been inserted, new music will be copied
                        #flashLED(0.1, 5)
                        #client.disconnect()
                        #loadMusic(client, CON_ID, device)
                        #mpdConnect(client, CON_ID)
                        #print client.status()
                        #flashLED(0.1, 5)
                        ## wait until thumb drive is umplugged again
                        #while checkForUSBDevice("1GB") == device:
                                #sleep(1.0)
                        #flashLED(0.1, 5)


                if GPIO.input(BUTTONS) == True:
                        buttonval = RCtime(BUTTONS)
                        if buttonval <= 180:
                                client.stop()
                                #client.status()["state"] = "stop"
                        elif buttonval <= 350:
                                client.next()
                        elif buttonval <= 500:
                                client.previous()
                        elif buttonval <= 850:
                                client.repeat(int(not int(client.status()['repeat'])and True or False))
                        GPIO.setup(BUTTONS, GPIO.OUT)
                        GPIO.output(BUTTONS, GPIO.LOW)
                        time.sleep(0.1)
                        GPIO.setup(BUTTONS, GPIO.IN)


                if GPIO.input(PLAYBTN) == True:
                        if timebuttonisstillpressed == 0:
                                # button has been pressed, pause or unpause now
                                if client.status()["state"] == "stop":
                                        client.play()
                                else:
                                        client.pause()
                                updateLED(client)
                        elif timebuttonisstillpressed > 4:
                                # go back one track if button is pressed > 4 secs
                                client.previous()
                                flashLED(0.1, 5)
                                timebuttonisstillpressed = 0
                        timebuttonisstillpressed = timebuttonisstillpressed + 0.1
                else:
                        timebuttonisstillpressed = 0

                sleep(0.02)

# Script starts here
if __name__ == "__main__":
    main()

Return to “Graphics, sound and multimedia”