First a quick background of my project. It's a remake of an "analog" laser spirograph I made a few years back. 4 small motors are setup with mirrors glued to the end. A laser is then reflected off each mirror. Varying the speed of each motor creates new designs. In this version the motors are wired up directly to pots. The new "digital" version I'm making uses a 20M2 where each pot is read into the MCU and the motors are controlled by PWM. It's also got a 16x2 LCD display and has has 4 modes:
![Smile :) :)](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
The problem I'm having is that the best designs usually come from only 2-3 motors running (or all 4 with 1-2 set very slow). But I also don't want to exclude having it run all 4 at higher speeds either, just not as often. Also, I'd like the transitions between designs to look/feel organic and not jumps between two completely different designs.
Ideally I kind of envision it starting on a design and holding for about 1s. Then it morphs into another completely different design, hold about 1s then repeat. I'm thinking I'd also like to have the morph time dependent on the user, so they can have it very quick to very slow, or an "auto" where it's random. This would be done with the selector pot.
Here's just some ideas I've tried and what I like and don't like about them:
My first attempt I just tried randomly choosing motor speeds. This looked okay, but I ended up getting those "jumps", which is why it's now part of my criteria. It also didn't account for more instances of only 2-3 motors running.
To fix the "jumps" I tried giving each motor two attributes, current speed and target speed. Each cycle it would increase/decrease the current speed until it hit the target speed, in which case it would assign a new random target speed. Rinse/repeat. This worked "okay" but it tends to not have much variation. Since each motor is constantly moving towards a target speed, they all tend to cross in the middle. It also seemed very unlikely that some combinations of speeds would essentially never be executed.
Finally I just decided to just try 4 embedded FOR loops that would cycle through EVERY possible combination. I liked the output on this, but with a total of ~14,500 possible combinations (11^4), you'd realistically never get to most of them. Also, the variations between iterations were so minor that it took a while before new designs came about.
Note: Although it has 10-bit PWM, variations between, say 234 and 235, are so inconsequential I went with having just 10 discrete speeds. The motors also wouldn't start turning until about ~270, and after about 80% duty, there was little to no noticeable difference. So my PWM output is calculated by PWM = Speed (1-10) * dutyStep (50) + dutyMin (300) or 350-800.
* An exception is made if speed = 0 since it would still produce a PWM of 300.
[EDIT] I forgot to mention, it might also be fun to create 2-3 different random algorithms that the user can choose between, with each having a different kind of "style". For instance, the first example of just picking random speeds would be fine if implemented with others.
- Manual - The user directly controls the motor speeds (0-10) with one of 4 pots. If there's a design they like, then can "Save to Favorites" which writes the 4 motor speeds to EEPROM.
- Favorites - Allows the user to browse, display and delete their saved favorites.
- Auto-Favorites - An "unattended" version of Favorites mode that just cycles through all their favorites automatically.
- Random - Just randomly picks motor speeds and displays them.
The problem I'm having is that the best designs usually come from only 2-3 motors running (or all 4 with 1-2 set very slow). But I also don't want to exclude having it run all 4 at higher speeds either, just not as often. Also, I'd like the transitions between designs to look/feel organic and not jumps between two completely different designs.
Ideally I kind of envision it starting on a design and holding for about 1s. Then it morphs into another completely different design, hold about 1s then repeat. I'm thinking I'd also like to have the morph time dependent on the user, so they can have it very quick to very slow, or an "auto" where it's random. This would be done with the selector pot.
Here's just some ideas I've tried and what I like and don't like about them:
My first attempt I just tried randomly choosing motor speeds. This looked okay, but I ended up getting those "jumps", which is why it's now part of my criteria. It also didn't account for more instances of only 2-3 motors running.
To fix the "jumps" I tried giving each motor two attributes, current speed and target speed. Each cycle it would increase/decrease the current speed until it hit the target speed, in which case it would assign a new random target speed. Rinse/repeat. This worked "okay" but it tends to not have much variation. Since each motor is constantly moving towards a target speed, they all tend to cross in the middle. It also seemed very unlikely that some combinations of speeds would essentially never be executed.
Finally I just decided to just try 4 embedded FOR loops that would cycle through EVERY possible combination. I liked the output on this, but with a total of ~14,500 possible combinations (11^4), you'd realistically never get to most of them. Also, the variations between iterations were so minor that it took a while before new designs came about.
Note: Although it has 10-bit PWM, variations between, say 234 and 235, are so inconsequential I went with having just 10 discrete speeds. The motors also wouldn't start turning until about ~270, and after about 80% duty, there was little to no noticeable difference. So my PWM output is calculated by PWM = Speed (1-10) * dutyStep (50) + dutyMin (300) or 350-800.
* An exception is made if speed = 0 since it would still produce a PWM of 300.
[EDIT] I forgot to mention, it might also be fun to create 2-3 different random algorithms that the user can choose between, with each having a different kind of "style". For instance, the first example of just picking random speeds would be fine if implemented with others.