Building the first Electro-Mechanical Pedal Steel Guitar

Technically it’s a closed loop stepper but operates similar to a servo, this is the part:

The belts drive a screw to move a carriage up and down. Hard to know if the belts will work especially given their 90 degree twist but I chose them because it’s a part that can be easily/cheaply sourced and assembled. Fingers crossed :crossed_fingers:

Hi Gus feel free to ask if you need any info. Also, you previously asked if I can add auto tuning to my guitar, well the answer is yes, it tune itself 100% accurately. 10 strings within 30sec

Okay, I’m back at it a bit! I have a new testbed, based on my latest drawings, and I have a servo wired up. When I tried to compile servo code for the teensy, I was told that servo.h didn’t support the processor. And since the teensy LC is old enough you can’t get them anymore, I bought an eps32 dev board. I am trying to run the stock servo test program, and running into this:

WARNING: library Servo claims to run on avr, megaavr, sam, samd, nrf52, stm32f4, mbed, mbed_nano, mbed_portenta, mbed_rp2040, renesas, renesas_portenta, renesas_uno, zephyr architecture(s) and may be incompatible with your current board which runs on esp32 architecture(s).
In file included from C:\Users\Administrator\AppData\Local\Arduino15\libraries\Servo\src/Servo.h:81,
                 from E:\Documents\Arduino\servoEPS\servoEPS.ino:10:
C:\Users\Administrator\AppData\Local\Arduino15\libraries\Servo\src/esp32/ServoTimers.h:3:33: error: 'SOC_LEDC_TIMER_BIT_WIDE_NUM' was not declared in this scope; did you mean 'SOC_LEDC_TIMER_BIT_WIDTH'?
    3 | #define LEDC_MAX_BIT_WIDTH      SOC_LEDC_TIMER_BIT_WIDE_NUM
      |                                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\Users\Administrator\AppData\Local\Arduino15\libraries\Servo\src/esp32/ServoTimers.h:5:43: note: in expansion of macro 'LEDC_MAX_BIT_WIDTH'
    5 | constexpr uint32_t BIT_RESOLUTION = (1 << LEDC_MAX_BIT_WIDTH) - 1;
      |                                           ^~~~~~~~~~~~~~~~~~
exit status 1

Compilation error: exit status 1

I’d have sworn the error message I got with teensy mentioned eps as compatible, but I don’t see it mentioned in the processor list for servo.h in the documentation.

What servo code did you run, Jacques? Is there an eps library out there?

I’ll keep looking around…

thanks!

-e

Okay, found the eps32servo library… back on track.

Teensy is actually a good choice, except if you would need to use wifi. If you need wifi a ESP32 S3 will work well in the long run if you need to go beyond only servos. if you can read freq the sky’s the limit–>>

Well, you kind of convinced me to at least try the wifi. Seems easier to run power to your pedals than a bunch of wires. The teensy LC I had was losing support. The EPS chips were not expensive.

I got the EPS running my servo via a pot. The servo demo code seems to send integer values to the servo, and I think I’ll need way more precision than that, so I’ll need to figure that out.

The motion is pretty jerky from a pot, so I need to get a hall effect sensor set up and working and see if that’s better. I’m curious about the details of how you worked the mechanics of the pedals and the sensor.

Also the servo is underpowered. My PS is 2.0 amps, but the servo draws 3.5 at 7.2v, probably closer to 4 amps at 8.4v… It works, but once I put it under load, moving the string, it jerks around. I’m curious how much power you spec’d for running 10 servos in various combinations… From what I was told over on the arduino forum, the servos will draw the stall power just holding the string in position. Thats 40 amps! A search on PSUs that size shows they are huge!

So I am curious what you are using.

I just left you a PM over at the steel forum with my email, if you want to get in touch that way.

well most of the adapters I’ve seen are 12 volt. Looking at step-down converters for that kind of amperage, they are used for Golf Carts!

Here’s an image of the current test bed… The changer finger will be stainless steel, and the little tuning collar will be printed from carbon fiber nylon. But it is all holding for now!

Jacques:

Did you use something like this for your pedals?

Or did you just use the simple 49e sensor? I guess the TI chip they use on this board also has temperature compensation. I don’t know if that is needed in this application… It also does angle computations. Not sure if that is more precise than position sensing.

Okay, I got one of the tmag5273 boards from adafruit, and am a bit confused how to wire it up to my eps32 board. Here’s the pinout for the eps:

I’d like to use the 4 pin cable connection. Black and Red are obvious, but the other two are I2C clock and data. SCL and SDA. I see there is support for I2C, but I’m not sure which pins to use for that.

Thanks!

You get to choose GPIOs that are not currently in use, and they will get connected inside the chip to the I²C controller. See this Reddit post for more.

thanks, that was just what I needed…

Okay, I am years behind Jacque, but here is a functioning knee lever moving the servo. I used the built-in smoothing on the hall sensor, and it seems to move pretty nicely.

My next issue is how to address multiple of these stemmaqt sensor boards with i2c addressing. I can’t find anything about setting addresses… I assume all 10 boards I bought will have the same address initially… And none of the code I found sets an address. Any clues most welcome thank you!

Hi there Eric. Why do you want to use tmag5273 boards, the esp boards have limited serial inputs. I use Hall Effect boards 4pin KY-024 Linear Magnetic Hall Switches with analog output and connect it directly to any green or purple pins.

There is a way to assign the addresses which I haven’t done, here the procedure: Addressing procedure

1. Connect TMAG5273 #1 to the ESP32-S3.

2. Leave TMAG5273 #2 through #10 disconnected from power.

3. Turn on the ESP32-S3.

4. The ESP32 finds TMAG5273 #1 at its factory address, for example 0x35.

5. The ESP32 tells TMAG5273 #1:
“Your new address is 0x30.”

6. TMAG5273 #1 is now 0x30.

7. Connect/power TMAG5273 #2.

8. The ESP32 sees #1 at 0x30 and #2 at the factory address 0x35.

9. The ESP32 tells #2:
“Your new address is 0x31.”

10. TMAG5273 #2 is now 0x31.

11. Connect/power TMAG5273 #3.

12. The ESP32 sees:

#1 = 0x30
#2 = 0x31
#3 = 0x35

13. The ESP32 changes #3 from 0x35 to 0x32.

14. Repeat the same process for #4 through #10.

At the end:

#1 = 0x30
#2 = 0x31
#3 = 0x32
#4 = 0x33
#5 = 0x34
#6 = 0x36
#7 = 0x37
#8 = 0x38
#9 = 0x39
#10 = 0x3A

do they remember their addresses then, after a reboot?

Wow, it’s surprising you can’t just set an address… but I will try that.

Yes the TMAG5273 save its new address. However if you lose one you have to re-address the new unit.

okay I hooked up a second unit… and… how do I know what addresses they got? And what is the syntax for getting the data from a specific unit?

I can find no example of using more than one of these units anywhere on the web.

it looks like I maybe could use something like:

Adafruit_TMAG5273 tmag;

tmag.begin(0x30);

However that particular code (I know you said the address was ‘for example’) results in the sensor not being found.

I found code to scan the I2C bus, but it’s only finding one device, at 0x35. I connected the second tmag while the EPS was running, but it did not seem to get assigned a new address. Or even be recognized on the bus?

// SPDX-FileCopyrightText: 2023 Carter Nelson for Adafruit Industries
//
// SPDX-License-Identifier: MIT
// --------------------------------------
// i2c_scanner
//
// Modified from https://playground.arduino.cc/Main/I2cScanner/
// --------------------------------------

#include <Wire.h>

// Set I2C bus to use: Wire, Wire1, etc.
#define WIRE Wire

void setup() {
  WIRE.begin();

  Serial.begin(9600);
  while (!Serial)
     delay(10);
  Serial.println("\nI2C Scanner");
}


void loop() {
  byte error, address;
  int nDevices;

  Serial.println("Scanning...");

  nDevices = 0;
  for(address = 1; address < 127; address++ )
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    WIRE.beginTransmission(address);
    error = WIRE.endTransmission();

    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");

      nDevices++;
    }
    else if (error==4)
    {
      Serial.print("Unknown error at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.println(address,HEX);
    }
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");

  delay(5000);           // wait 5 seconds for next scan
}

Hi there. If esp find one it is a good thing as it reads it. Disconnect all and leave one connected. It will show address x 35. Change the address to x 30 and recompile. The address for that module is now x 30, then connect the next and do the procedure again. I gave the procedure 5days ago which includes the addresses you need to assign to each module. Make sure you mark the modules as you program them. Then connect them in series. Each module will send its data with its address at the start and esp will use the data.