fijam / gmdrec

gmdrec is a USB interface between your late 90's Sony portable MiniDisc recorder and your PC.
https://www.tindie.com/products/fijam/gmdrec/
BSD 3-Clause "New" or "Revised" License
28 stars 6 forks source link

Trouble using 3b Device #32

Closed spbkaizo closed 4 months ago

spbkaizo commented 6 months ago

Hi,

First up - THANKS for creating this project. I've built a rev. 3b board, all seems to be OK with the soldering as far as I can determine but perhaps not!

When I try and run mdrec, I get this back:

<simonb@odin:~/src/gmdrec>
zsh 563  (git)-[main]-% ./mdrec.py 
Traceback (most recent call last):
  File "/home/simonb/src/gmdrec/./mdrec.py", line 13, in <module>
    from hardware import pulldown_on_data, cleanup_exit
  File "/home/simonb/src/gmdrec/hardware.py", line 125, in <module>
    pot = I2CDevice(i2c, 0x2C)
  File "/home/simonb/.local/lib/python3.9/site-packages/adafruit_bus_device/i2c_device.py", line 62, in __init__
    self.__probe_for_device()
  File "/home/simonb/.local/lib/python3.9/site-packages/adafruit_bus_device/i2c_device.py", line 175, in __probe_for_device
    self.i2c.writeto(self.device_address, b"")
  File "/home/simonb/.local/lib/python3.9/site-packages/busio.py", line 207, in writeto
    return self._i2c.writeto(address, buffer, stop=True)
  File "/home/simonb/.local/lib/python3.9/site-packages/adafruit_blinka/microcontroller/mcp2221/i2c.py", line 22, in writeto
    self._mcp2221.i2c_writeto(address, buffer, start=start, end=end)
  File "/home/simonb/.local/lib/python3.9/site-packages/adafruit_blinka/microcontroller/mcp2221/mcp2221.py", line 333, in i2c_writeto
    self._i2c_write(0x90, address, buffer, start, end)
  File "/home/simonb/.local/lib/python3.9/site-packages/adafruit_blinka/microcontroller/mcp2221/mcp2221.py", line 251, in _i2c_write
    raise RuntimeError("I2C slave address was NACK'd")
RuntimeError: I2C slave address was NACK'd

Hoping you can give a steer to troubleshoot - is it likely this is an issue with a soldering of the potentiomenter?

My deviations from your schematic are that I used 2x 5.6k resistors for R3 and R4 as I didn't have any 4.7k's.

Thanks again!

fijam commented 6 months ago

Hi,

5.6k pullups should be perfectly fine.

This could definitely be a problem with the soldering, the error indicates that the usb-i2c bridge cannot see the digital pot on the i2c bus.

spbkaizo commented 6 months ago

Hi,

This is a 'me' problem - I was actually using an MCP4551-503E as I incorrectly guessed it would be a drop in replacement. I'm just trying to figure out the changes (the i2c addresses for one!) needed to get it to work.

spbkaizo commented 6 months ago

I'll report back later, but for now I'm at least able to converse with the device via the i2c bus.

Doing a test recording which I expect to fail (but I now have blinkenlights!), another quick question...

I have an R900, can you advise which setting I'd be better off using for the 'label' argument on the command line? Currently using 'R909/R910/N1'.

fijam commented 6 months ago

I am guessing you mean the 'recorder' argument, R900 should be in the 'R70 through N707' group of recorders. Make sure to choose 'R70 through N707 JPN' if you have the domestic variant (i.e. you can use katakana in labeling).

Double-check your calibration with a multimeter, you want to be as close to the reference values as possible https://github.com/fijam/gmdrec/blob/main/settings.conf

Since mcp4552 does not have non-volatile memory, make sure it takes the calibration values from the settings file instead of trying to read it from the pot. edit: this should be fine, values in the settings.conf file take precedence: https://github.com/fijam/gmdrec/blob/main/hardware.py#L147

Make sure you have the 'phrase book' empty since it will throw gmdrec off.

In addition, there may be some labeling-related differences based on firmware revisions so let me know if there are some letters it gets wrong.

spbkaizo commented 6 months ago

Double-check your calibration with a multimeter, you want to be as close to the reference values as possible https://github.com/fijam/gmdrec/blob/main/settings.conf

Can you please confirm which pins I should take the readings from? Thanks.

fijam commented 6 months ago

Sure, you need to measure the resistance between pins 2 and 4 of the device (see https://github.com/xunker/SonyMDRemote/tree/master/connector)

You will need a small helper script that sets the digital pot to the tested values and holds it there so you have enough time to make the measurement.

Something like this:

#!/usr/bin/python3
import os
os.environ["BLINKA_MCP2221"] = "1"

try:
    import board
    import busio
    i2c = busio.I2C(board.SCL, board.SDA)
except RuntimeError:
    print("uhoh")

def digipot_setup(address):
    from adafruit_bus_device.i2c_device import I2CDevice
    pot = I2CDevice(i2c, address)
    return pot

def shutdown_pot():
    pot.write(bytes([0b01000000, 0b11111001]))

def reenable_pot():
    pot.write(bytes([0b01000000, 0b11111111]))

def write_to_pot(value):
    pot.write(bytes([0x00 & 0xff, value & 0xff]))

# These should correspond to 200, 1000, 3650, 5160, 7100, 9900, 11900, 14300, 16700 and 19500 Ohm
values = [0, 5, 19, 26, 37, 52, 62, 75, 87, 102]

print(i2c.scan())
pot = digipot_setup(0x2C)

reenable_pot()
for value in values:
    write_to_pot(value)
    print(f'wiper set to {value}')
    input('next?')

shutdown_pot()

adjust as needed for mcp4551

spbkaizo commented 6 months ago

Thanks,

Results are here:

uninitialized - 23.58K
...
wiper set to 0 - 48.3k
wiper set to 5 - 47.4k
wiper set to 19 - 44.8k
wiper set to 26 - 43.4k
wiper set to 37- 41.4k
wiper set to 52 - 38.5k
wiper set to 62 - 36.7k
wiper set to 75 - 34.26k
wiper set to 87 - 32.05k
wiper set to 102 - 29.19k
...

shutdown - ~8.6-10.0M

I'm quite a distance from the reference values! Indeed, I'm going the opposite way (i.e. should start at 255)

150 gives me 20K
200 gives me 10k
255 gives me 273 ohms

I'll do some testing and figure out what the values I need are, and report back.

Thanks for your help on this, and apologies for delays in my replies .

fijam commented 6 months ago

I believe that's because mcp4551 is in a potentiometer configuration and mcp4562 is in a rheostat configuration (which is just like 4552 below, just with non-volatile memory)

image

So instead of connecting P0B to P0W, you are doing P0A to P0W, which is why everything is inversed. But as long as you can get the right resistance values it should work either way. Although you might want to leave pin 7 floating? I'm not entirely sure.

spbkaizo commented 6 months ago

Thanks,

A quick update - I've identified the closest values for this chip.

For others who end up in the same boat, I amended your test program to ask the user for the values, and then write them to a file for future reference.

#!/usr/bin/env python3
import os
import sys

# Set up environment variable for MCP2221
os.environ["BLINKA_MCP2221"] = "1"

try:
    import board
    import busio
    from adafruit_bus_device.i2c_device import I2CDevice
except ImportError as e:
    sys.exit(f"Failed to import required modules: {e}")

try:
    i2c = busio.I2C(board.SCL, board.SDA)
    print("I2C initialization successful")
except ValueError as e:
    sys.exit(f"I2C initialization failed: {e}")

def digipot_setup(address):
    global pot
    pot = I2CDevice(i2c, address)

def shutdown_pot():
    global pot
    pot.write(bytes([0b01000000, 0b11111001]))

def reenable_pot():
    global pot
    pot.write(bytes([0b01000000, 0b11111111]))

def write_to_pot(value):
    global pot
    pot.write(bytes([0x00 & 0xff, value & 0xff]))

# Change potentiometer address as required
pot_address = 0x2E
digipot_setup(pot_address)

# File to save the readings
file_path = "potentiometer_readings.txt"

print("Enter a value for the potentiometer (0-255). Type 'exit' to quit.")
while True:
    try:
        input_value = input("Enter value: ").strip()
        if input_value.lower() == 'exit':
            print("Exiting program.")
            shutdown_pot()  # Ensure the potentiometer is properly shut down before exiting
            break
        pot_value = int(input_value)
        if pot_value < 0 or pot_value > 255:
            print("Value out of range. Please enter a value between 0 and 255.")
            continue
        write_to_pot(pot_value)
        measured_value = input("Enter the measured value in ohms: ").strip()
        print(f"Written value: {pot_value}, Measured value: {measured_value} ohms")
        with open(file_path, "a") as file:
            file.write(f"Written value: {pot_value}, Measured value: {measured_value} ohms\n")
    except ValueError:
        print("Invalid input. Please enter a numeric value.")
    except IOError as e:
        print(f"File operation failed: {e}")
        break

And, the magical values are:

calibration:
  Play: 255 (273 ohms)
  Left: 251 (1K)
  Right: 237 (3.668K)
  Pause: 229 (5.17K)
  Stop: 219 (7.07K)
  VolUp: 204 (9.90K)
  TMark: 193 (11.97K)
  Playmode: 181(14.22K)
  Display: 168 (16.67K)
  Record: 153 (19.53K)

I'll do some more testing and report back.

spbkaizo commented 6 months ago

Hi, so running it with a command line of python mdrec.py "%artist% - %title%" "R70 through N707" it correctly finds the playlist, however it simply flies through and exits so I suspect we're not able to trigger it on an R900.

I notice that the device does a little 'click', also it sometimes flashes up quickly a message about 'High DC'. Any ideas?

fijam commented 6 months ago

Hi, so running it with a command line of python mdrec.py "%artist% - %title%" "R70 through N707" it correctly finds the playlist, however it simply flies through and exits so I suspect we're not able to trigger it on an R900.

Can you describe what happens in a bit more detail? This is roughly how it should look like (it takes about 30 seconds to label a track):

https://github.com/fijam/gmdrec/assets/75824/9f3fc9a8-eb21-4596-adb0-623523ee8362

Once the progress indicator shows up the LED should start blinking.

I notice that the device does a little 'click', also it sometimes flashes up quickly a message about 'High DC'. Any ideas?

'High DC' definitely doesn't sound right. How do you connect it to the R900? Sounds like a wiring issue somewhere.

fijam commented 6 months ago

And just to confirm, R900 definitely should work as I have a report from a user of one. (I personally only have R90 and R909 which are very similar electronically as well)

spbkaizo commented 6 months ago

Aloha - Sorry for the delay again.

The app simply runs straight through immediately, and exits after a few seconds.

zsh 777  (git)-[main]-% time python mdrec.py "%artist% - %title%" "R70 through N707"
Total playlist duration: 0:41:41
The playlist contains the following tracks:
['NewDad - Angel',
 'NewDad - Sickly Sweet',
 'NewDad - Where I Go',
 'NewDad - Change My Mind',
 'NewDad - In My Head',
 'NewDad - Nosebleed',
 'NewDad - Let Go',
 'NewDad - Dream of Me',
 'NewDad - Nightmares',
 'NewDad - White Ribbons',
 'NewDad - Madra']
Wait for REC Standby...
Cleaning up.
Bye!
python mdrec.py "%artist% - %title%" "R70 through N707"  0.70s user 0.07s system 18% cpu 4.203 total

This is with the board disconnected. However, the same happens with the board connected. A question is around what the correct behavior is - does the app check to see if the board is connected ?

Here's some of the resistances I've observerd:

USB disconnected  >16M 
Plugged into USB - 25K
Initial program start - 0L (i.e. not connection)
After the initial start (&exit) the resistance goes to 3.3M

I obviously made some changes to pick up the new i2c address, I'll raise a PR so you can see them, perhaps it is something obvious in there! https://github.com/fijam/gmdrec/pull/34

Thanks.

spbkaizo commented 6 months ago

Edit: I ran wireshark, and see connections - the last one returns the playlist, but then no attempt is made to the API to play the tracks...

(file is actually a .pcap)

local_http.txt

fijam commented 6 months ago

A question is around what the correct behavior is - does the app check to see if the board is connected ?

It doesn't - it should happily try to type the track names without a recorder plugged in. Let's not worry about it until we can get it working in a dry run.

Which versions of beefweb/deadbeef are you using?

spbkaizo commented 6 months ago

You're a hero for helping out with this, thank you!

I'm on 1.8.8 of DeadBeeF and I've just tried 1.9.6.

I've also just tested 0.8 and 0.7 of beefweb with 1.9.6, and see the same behaviour.

If you can confirm which versions you use, I'll try them and see what happens.

fijam commented 6 months ago

I booted Fedora 39, installed deadbeef 1.9.6 from RPM fusion and beefweb 0.8.0 and it seems to work fine:

Td6Yx1n

It looks in your screenshot like it crashes just after receiving the list of tracks as it tries to issue the first command to the digipot. Unfortunately I don't have more time to look into this today, but I'd recommend adding some debugging around hardware initialization (maybe re-raise exceptions in the try block).

spbkaizo commented 6 months ago

I'm an idiot - https://github.com/spbkaizo/gmdrec/blob/main/hardware.py#L75

Omitted the 'value' being passed in. Working now though not yet connected it to the MD player to test.

Thanks.

fijam commented 6 months ago

Ah, that makes sense. BTW, you will probably need the 'resume from shutdown' command for mcp4551 as well.

I am still a bit concerned about the 'high dc' error you've seen before, can you confirm how you connect the board to the MD recorder?

spbkaizo commented 6 months ago

So the high dc error occurs if I try to use the device when +3v external is applied. It also sporadically appeared when 'jiggling' the connector into the MDR. This was my attempt at debugging :-)

I've now got the device connected ok - I see messages where it is trying to volume controls (up, and down I think) and then a 'sorry' message appears. I'm guessing I need to play with the calibration values a bit more...

This is the current function for writing values:

def write_pot_mcp4551(value):
    pot.write(bytes([0x00 & 0xff, value & 0xff]))
    pot.write(bytes([0b01000000, 0b11111111])) # re-enable pot
fijam commented 6 months ago

Can you please attach a picture of your setup?

spbkaizo commented 6 months ago

Sure, does this help?

IMG_3167 IMG_3166 IMG_3165

fijam commented 6 months ago

Okay, I think what is tripping you up is the GND

With MCP4562 GND network looks like this: image

With MCP4551 this is no longer true, as pin 7 is P0B - this is probably why you are getting weird DC errors.

You need to leave pin 7 floating and connect the recorder ground to the device ground, something like this:

image

fijam commented 6 months ago

The easiest way to do that (if you don't want to cut the traces) would be to simply cut the leg of pin 7 of MCP4551.

spbkaizo commented 5 months ago

You're amazing.

Yep - it's almost there now - titles are being entered (but with a few mistakes) so I'll tinker with the settings to see if I can tighten them up.

Thanks for all your help, and especially your patience!

fijam commented 5 months ago

I'm glad to hear that and that my intuition was correct :)

You can also try playing around with the amount of time for each key press, which is set in https://github.com/fijam/gmdrec/blob/main/definitions/r90.py#L6 (if you use the 'R70 through N707' recorder type). Making it a little longer might reduce the number of mistakes (although it's been already extended, originally it was only 35 ms). A few typos per a tracklist is usually unavoidable in any case.