Giter VIP home page Giter VIP logo

espels's People

Contributors

digiexchris avatar jschoch avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

espels's Issues

backlash compensation

consider a config parameter and some movement to ensure that backlash is removed before trying to sync move

clean up deps

lib_deps =
REMOVE squix78/ESP8266_SSD1306@^4.1.0
???? someone may want buttons like an estop! thomasfredericks/Bounce2@^2.55
REMOVE most likely bricofoy/YASM@^1.0.4
Don't think I"m using janelia-arduino/Vector@^1.2.0

Keep and or update

me-no-dev/ESP Async WebServer@^1.2.3
bblanchon/ArduinoJson@^6.17.2
bblanchon/StreamUtils@^1.6.1

Current bugs from testing 0.0.3

Bounce mode doesn't seem to work, or at least maybe a bug moving back and forth between unit types. When I did get it to move in bounce it appeared to be moving in metric with an inch value. It was also switching the front-end into a bounce mode enum with a blank page blow it, I had to switch back to movesync and then bounce tab to cancel it further attempts at bounce did no moves.

In move sync mode the left rapid moves correctly to the left. The right rapid moves incorrectly to the left instead of the right.

Unit conversions still seem broken. Move distance converts ok, but the pitches sometimes don't convert properly when switching units back and forth. Not sure what causes it. Sometimes it works, sometimes it doesn't and I end up with a very long slow pitch like 0.000000577853

Good news is there only seems to be about 0.06 mm error over 25mm. I cut a 20tpi thread that was 3/8" long that fit well so it at least satisfies my short thread needs.

Math question

Hello again. I have been using your project for a couple weeks and I believe it works as you intended. I have a strange issue with the math with regard to feed per rev. When I dial up 25mm in the move sync mode with backlash out of the system, I only move 24.840. It's repeatable and linear so it stacks up over distance. The puzzling thing is that I thought if I was off it would be by a multiple of something or a reasonably round percentage, but it's this oddball number. There are some things I had wrong out of the gate; the encoder I was sent was 600 cpr not 360 as I thought, which was exacerbated by the fact that the encoder runs at 2:1 vs. the spindle due to gearing. I also failed to factor in the 4:1 ratio of the servo to the leadscrew, but these were the dumb errors I was expecting, not to come up .6% short. Any ideas? The only thing approaching a glitch I've found is that when you cancel a bounce move early, it still runs the entire return cycle at speed. This can cause some excitement and happens just when you start to trust the thing. I had a hell of a time with hardware this time as never before with the ESP32. I had some transients or similar causing flash corruption and hangs on boot. I have moved the pulse and direction pins to 22 and 23, there's some talk in the documentation about GPIO 12 causing serious misbehavior if pulled high during boot and causing this, and it seems better. I've mitigated noise as much as possible but there's a couple switching supplies sharing the enclosure which makes it a challenge. It's behaving now, I am getting used to the web interface but I wish the buttons were bigger. It is very responsive with a robust connection. Thanks again, it works a treat.

Question

Still working on this project?

CORS and SSE

I did some research on the CORS issue again, here's the state of things.

CORS-RFC1918 prevents "more private" network connections without a preflight " Access-Control-Allow-Private-Network: true" header sent from the browser and acked from the esp32. There is no issue if you are serving the static html from your private network. Adding the header on the esp32 is fairly easy to do but....

EventSource API does not allow you to add headers and...

Chrome/Firefox don't issue the preflight request because they don't seem to see the rfc1918 address, but they do kill the connection because they see a rfc1918 address....

So, it appears I need to re-write the frontend to use a polyfill that allows for event source preflight headers to be sent via the fetch() api.

Before I do that I plan on taking the current experimental branch and getting them released which should allow for configurable SSE or Websockets for updates, as well as options for interrupt driven/timer driven control logic.

Configuration in progress

Here are a few photos and some questions:
20231205_162231 1
20231205_162201 1
20231205_162137 1
20231205_162149 1
As you can see, I got lucky and was able to shoehorn the servo in the unused space under the headstock on this particular lathe. The levers on the front are three position switches; one on the right is maintained and the left one is momentary. I would like the maintained one to determine direction. I was also thinking that the existing hall sensor that was used by the factory tachometer could be put to work as an index pulse to synchronize the carriage

local display using wired communication, buttons, tft.

What are your UI plans for a wider release? I suppose my question is, will it be possible to port this over to a local display using wired communication, or possibly a second ESP to share the comms and processing burden and communicate locally over ESPnow or similar. I assume that once the project is complete in your eyes, the need for OTA development updates will be greatly diminished and possibly outweighed requests for a wired solution. I am not questioning your vision, just asking a question. I just saw a tft display using an ESP for the controller, and they even broke out a few IOs for you to use. That's interesting.

It is open source so if someone wants to make a frontend that has wired controls and a TFT display then I'm more than happy to help them understand how to "plug in" and to collaborate on an API to do this. This is one of the reasons the "frontend" is in a separate repo.

However, i'm not going to maintain that code and I have no interest in a TFT UI or physical buttons, been down that road and it is very rigid and inflexible. So sure it can be cone but you'll need someone who can code and who will maintain it and who also happens to pick a TFT, button layout, encoder input etc that you like.

Broaching mode

Just a simple addition to bounce mode where it continually does a normal feed to depth, rapids out, pauses for a configurable amount of time, and runs it in again. It would need to not be synced to the spindle. I would use this to help me broach keyways on the lathe. I'd just fed in a thou or so when it withdraws from the bore between passes.

LED status

considering 2 setups:

simple: CONTROLLER_ERROR_LED, WIFI_STATUS_LED

advanced:

ws2812_CONTROLLER_STATE  {
  startup_mode: yellow,
  running_mode: orange;
  conjestion_mode: blue;
 ready_mode: green;
  errors: white;
  halt: red;
}
ws2812_WIFI_STATE {
  congestion_mode: white;  // this is when the websocket queue is getting full
  bad_signal_mode: yellow;
  good: green;
 not_connected_to_wifi: red
  no_clients_connected: blue;
}

Debug feature: Have stepper move in an exact number of steps in a particular direction

Considering I (and others) are going to try to do threading operations in the opposite measurement system than the leadscrew is (eg. an SAE leadscrew doing metric threads) it would be nice to have a way to experimentally measure the actual error given with a certain distance. I'd like a box on the debug screen with the number of steps (microsteps in this case, since that has torque implications too) to move, and a button for making it go in a certain direction. That way I can pre-calculate the number of steps required to make the carriage move the length of the bed, and use my DRO to see how close it came. I want this instead of distance, because I want to be able to separate any math errors coming from my converting my leadscrew to metric in the firmware (floating point rounding errors, accumulating errors, etc) from the results. Might be an easy frontend change?

Hobbing setup

I'm super interested in your setup for hobbing, do you have any pictures of the machine setup to do work?

Unexpected behavior in Move/Sync mode

While doing testing, I used the move synced to spindle mode in concert with the DRO to resolve a ratio problem. It worked as expected, but when I tried to run a bounce move immediately after, the move continued past the expected return point and continued running after dis-engaging the half nut to avoid a crash. The move cancel button has been removed so the only way to stop the control is by emergency stop, but this doesn't resolve the problem when starting back up. The controller has to be reset. I will attempt to flash the project on a new controller to reduce the likelihood of a hardware problem.

threading offset

Small offset for threading when feeding in needs to be added.

SAE lathe options

Hello! I'm about to dive into this myself. Just wondering if you've implemented inch threads or use with inch leadscrews? I'm a software engineer myself so I can probably take care of it, just wondering if you've considered it and how you would approach that problem. Especially any problems you envision with error in converting metric threads on an imperial leadscrew and visa-versa. I'm thinking that there are thread conversions that will never perfectly resync once started, but I suspect if we accept a certain low percentage error (tuneable/calculateable through the frontend perhaps), it will be more than good enough. Of course, adapting the frontend to convert TPI to distance in lead is easy enough...

stepper enable/disable

it is handy to turn off the stepper to reposition. add this to the GUI and make a physical button/switch option.

architectural possibilities

Appologies for the long essay. This is an idea of how I'd like to reorganize the code base into C++ style concepts. I can submit PRs with very small proofs of concepts, perhaps converting a single small concept at a time, if that helps it make it clearer. I'll make more issues with ideas to change the machine functionality as I come across them, but this is specifically about the shape of the codebase in general.

I would like to spend some time if you're willing to let me converting some of this into c++ objects and separating the concerns and internal state into logical chunks. I think it would make future development a lot faster by calling getters and convenience functions on instances of an object rather than having to have to know about how the internal state of another area of concern works.

split headers and initializsers into a precompiled header, and then the initializer in the .inl. the PCH can then avoid the huge chain of includes at the top of every file.

For example, one main state machine class that handles the runmodes and other common states that multiple modules use. Other modules call functions to get and change state. Alternatively, an event based system as a later step 2.

Web calls State for basically an array (I'd make a DisplayOutput interface or something), rather than getting DRO position directly from memory. Then we can strip out Web and replace it with another implementation without touching State. Also, it allows us to make alternate interfaces that interact with State with the same api, but over a different method (such as, i2c to a backpack board or something).

  • I'd like to make some common abstractions, which can be generic, which can be extended by specific use cases.
    -- Such as, the RMT stepper controls the hardware. That's good. Wrap it in a generic Stepper that extends RMTStepper that takes pin configuration, microstepping, steps per rev etc. at instantiation time
    -- Leadscrew can either extend Stepper, or have a stepper object in it. I'd prefer Leadscrew to have a MovementDevice which would be an abstract class that is overridden by Stepper. So Leadscrew can instantiate a Stepper, which because of the MovementDevice abstraction, has the same API regardless of wether it's actually a leadscrew, or turning the carriage handle on a rack and pinion, or some other kind of control. Leadscrew can contain things like SAE or Metric, how to convert between the leadscrew system and the stepper coordinate system (sae or metric), and can give instructions to the stepper in distance or steps.
    -- Machine can have a leadscrew (or more leadscrews, in the case of mill feeding or cross slide feeding or something), and can ask the leadscrew to move a distance in the current coordinate system eg. With a metric leadscrew, and the machine in SAE mode, Machine's Move() can contain myLeadscrewInstance.Move(this.coordinatesystem, "0.001f"); and then the stepper will convert coordinate systems to the stepper system, and then tell the stepper to move a certain number of millimeters. Or steps, alternately. Then Stepper calls rmtStepper functions to do the work.

  • State
    -- StateMachine Event
    ---RunMode
    ---MoveTo
    ---Output DRO

  • Machine
    -- MovementDevice
    --- Leadscrew
    ---- Stepper
    ----- RMTStepper
    --- RackAndPinion
    ---- SomeHardwareImplementation

  • HumanInterfaceInput interface
    -- Web
    -- Buttons
    -- Nextion interface over i2c

  • HumanInterfaceOutput Interface
    -- Web
    -- i2c Backpack LCD
    -- Nextion screen presses turned into State Machine commands over i2c

Example workflow:
Button press to change to SAE:

  • Fires a MeasurementSystemSAE event
  • Machine takes the event
    • Calculates the new Leadscrew ratio parameters
    • Calls functions on Leadscrew to update those parameters
      --- Leadscrew updates parameters on Stepper, which then knows how to call RMTStepper next time.
  • DisplayController (or whatever owns the HumanInterface stuff) Sends a DisplayUpdate event containing the payload that has the new measurement system
    -- Web, being subscribed to that event, fires off the updated data into the websocket

And, at runtime or compile time, we can turn on or off all of these features just by constructing the objects differently.

A couple of use cases this helps with:

  • a lathe that has a 127 tooth metric/SAE conversion gear) that is selectable in a gearboax or something easy to use, you can gain more accuracy and less error, just by setting up the Leadscrew object with the same values, just a different coordinate system and a different ratio and it can figure it out. Can define it as two leadscrews, and swap back and forth between them by their ID in a list. Maybe key the list by measurement system?

  • It also allows for easily writing a different kind of motor driver, under the MovementDevice contract. Hobby servos, whatever the end user fancies. Or, like we're discussing, replacing the stepper acceleration algorithms. The same api means we can have both in the code and A/B test or even allow the user to select one at config time.

  • Maybe most importantly, it makes clear distinctions on areas of code and how memory is laid out, which is beneficial to getting more people to contribute. Easier to understand at a glance, easier to unit test in isolation, and easier to submit changes to small chunks of code for small improvements instead of needing a large effort to refactor

-- Provides important improvements and easy to use mutexes for thread safety

Anyway, this is a request for comments with the offer of me doing most of the work if you would like. I don't expect you to drop everything for this :) My web front end skills are weak, but c++ is something I'm familiar with.

serial test commands

write some test commands you can initiate from the serial console thus removing the frontend from troubleshooting

Migrate to ESP_IDF

In order to ease debugging and warning of unexpected behaviour, I think turning these on in the sdkconfig will help.

Heap Poisoning
Stack Smashing Protection Mode
UBSAN should help too with extra compile time checks and is probably generally useful for preventing bugs including divide by zero bugs.
https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-guides/fatal-errors.html

There is performance implications for these, but might not be much. We can always turn them off for a full release.

Hardware details?

Any photos or description of how you mounted the motor to your lead screw and what motor / driver you are using?

I have the same lathe, and have enough spare steppers/servos, ESP boards to build this. Would like to have similar gearing to your setup so that we can share code with no modifications.

threading without a compound use case for work offsets

image

There are multiple threading strategies available, this focuses single sided with variable depth starting from a Z+

  1. user configures lathe in start position (G54.1 "0"), with enough lead to remove any acceleration errors
  2. User inits threading dialog in UI
  3. Dialog asks for thread parameters
  4. User enters parameters: first thread depth, thread length (how far in Z to cut the thread), handedness, number of starts
  5. Dialog calculates number of passes, depth per pass, and offset required to simulate the compound,
const passes = () => {
    let p = Math.ceil(Math.pow(((config.pitch * 0.614) / firstThreadDepth),2));
    if(Number.isInteger(p)){
      return p;  
    }else{ return 0}
  }
fir (var current_pass=1; i <= number_of_passes; i++){
 feed = (thread_depth/Math.sqrt(number_of_passes -1)) * Math.sqrt(current_pass-1);
  1. outputs a table
  2. User confirms by clicking start

This is where it is a bit tricky because we depend on the user to feed X in and out, and the lathe is likely small and not very rigid, we may need to run the same depth more than one time. This is where I want to use the offsets.

pitch: 1.5mm Thread Depth: 0.921 Recommended Passes: 22Initial Offset: 0.2 Offset per pass 0.06818181818181818

pass 1: the offset is the starting position, nothing really needs to be done here other than the operator moving the X
pass 2: first offset. Dialog confirms pass 1 complete, then stores the original offset, we'll call that G54.1, the machine then creates a new offset G54.2 offset in Z- by the calculated amount (.068mm) and changes to use that offset.

if the user wants to change back to the original offset they can select the pass "#" from the UI.

pass 3: same as pass 2 but uses G54.3 to store the new offset

for multiple starts we'd could make an offset of offsets, but likely not worth it to so this abstraction.

...

finish: delete offsets from threading or leave them in there?

We could also add some backlash compensation to ensure the lead screw slack is removed before the thread feeding starts.

so, we'd need


// 1. doubt this needs to be int64_t
// 2. if we do this in steps need to ensure everything from/to the UI is in steps
int64_t offset[3]

home instance //  position at machine start.  This is tricky because you frequently move everything around with the half nut and this may quickly become meaningless
float backlash.z, backlash.x
offsets[20] // ? not sure what a good number is but there is plenty of memory available
uint_8_t current_offfset // offsets index
uint_8_t last_offset // offsets index
double offset_in_mm( offset_3 ) // function to translate steps to mm

@digiexchris let me know if this is clear enough for you.

renaming movements, getting rid of the use of "jog" everywhere

Jog( speed, distance ) where the Z moves without the spindle moving. This is very rarely used.

SyncMove( pitch,distance, handedness {CW || CCW}) where the Z moves in sync with spindle based on the current "gear" configuration and pitch setting. This assumes the spindle will stay running in the same direction and the handedness of the spindle makes it a bit tricky. These moves are always relative to the current position.

AbsoluteSyncMove( position ) this would move to a "DRO" position based on the current position.

maybe needed AbsoluteJog(speed,position)

comments?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.