Skip to content

Feat/module code #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Apr 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
# SplitFlap

modernized split flap
A modernized split flap display.

<div style="text-align: center;">

![SplitFlap](./assets/splitFlap2.png)

</div>

#### Characters

26 `A B C D E F G H I J K L M N O P Q R S T U V W X Y Z`
10 `1 2 3 4 5 6 7 8 9 0`
10 `? ! & ' - = ; : , .` `@ # $ ^ * % / +`
2 `blank □ full ■ `
26 `A B C D E F G H I J K L M N O P Q R S T U V W X Y Z` \
10 `1 2 3 4 5 6 7 8 9 0` \
2 `blank □ full ■ ` \
14 `? ! + - = * ' : , . @ # % €/$` <!-- & ^ ; --> \

`0 O` and `1 I` can share the same flap

<!-- 26 + 8 + 2 = 36 -->

## Parts

Expand All @@ -23,4 +33,4 @@ A4988 Stepper Motor Drivers

### Micro controller

Esp32
Esp32 / Arduino pro micro
Binary file added assets/splitFlap1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/splitFlap2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified barrel/barrel.SLDASM
Binary file not shown.
Binary file removed barrel/blockingTab.SLDPRT
Binary file not shown.
Binary file modified barrel/circleMount.SLDPRT
Binary file not shown.
Binary file modified barrel/circleOpen.SLDPRT
Binary file not shown.
Binary file added barrel/flapStopper.SLDPRT
Binary file not shown.
Binary file modified barrel/motorBackSpacer.SLDPRT
Binary file not shown.
Binary file removed barrel/motorConnector.SLDPRT
Binary file not shown.
Binary file removed barrel/motorConnectorThicc.SLDPRT
Binary file not shown.
Binary file removed barrel/motorMount.SLDPRT
Binary file not shown.
Binary file removed barrel/motorSpacer.SLDPRT
Binary file not shown.
Binary file removed barrel/motorSpacerRound.SLDPRT
Binary file not shown.
Binary file removed barrel/spacerBig.SLDPRT
Binary file not shown.
Binary file removed barrel/spacerBigSlot.SLDPRT
Binary file not shown.
Binary file removed barrel/spacerSmall.SLDPRT
Binary file not shown.
Binary file removed body/front.SLDPRT
Binary file not shown.
Binary file removed body/lager.SLDPRT
Binary file not shown.
Binary file modified body/screwFront.SLDPRT
Binary file not shown.
Binary file modified body/sideLeft.SLDPRT
Binary file not shown.
Binary file removed body/sideMinimal.SLDPRT
Binary file not shown.
Binary file removed body/sideMount.SLDPRT
Binary file not shown.
Binary file modified body/sideRight.SLDPRT
Binary file not shown.
Binary file removed body/uniBody.SLDPRT
Binary file not shown.
Binary file removed card.SLDPRT
Binary file not shown.
25 changes: 20 additions & 5 deletions code/module/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,15 @@
#define RXD1 21

// defines pins
#define STEP_PIN 13
#define DIR_PIN 12
#define STEP_PIN 22
#define DIR_PIN 23
#define HALL_PIN 15

SplitFlap splitFlap(STEP_PIN, DIR_PIN);
SplitFlap splitFlap(STEP_PIN, DIR_PIN, HALL_PIN);

// Use Serial1 for UART communication
HardwareSerial mySerial(2);

SplitFlap splitFlap(13, 12);

bool readingPacket = false;

void handleMyByte(uint8_t byte)
Expand All @@ -31,14 +30,30 @@ void setup()
mySerial.begin(9600, SERIAL_8N1, RXD1, TXD1); // UART setup

splitFlap.init();
splitFlap.home();

Serial.println("Module started");
}

uint8_t flapIndex = 40;

void loop()
{
splitFlap.update();

// move flap every 200ms
static unsigned long lastMove = 0;
if (millis() - lastMove > 5000)
{
flapIndex = (flapIndex + 1) % 50;

Serial.printf("Setting flap to index: %d\n", flapIndex);
splitFlap.setFlap(flapIndex);
// splitFlap.moveFlaps(51); // TODO: make sure this also works with > 50

lastMove = millis();
}

// Check if data is available to read
if (mySerial.available())
{
Expand Down
113 changes: 63 additions & 50 deletions code/shared/include/SplitFlap.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,59 +13,89 @@
class SplitFlap
{
public:
SplitFlap(int stepPin, int dirPin)
SplitFlap(int stepPin, int dirPin, int hallPin)
{
this->stepPin = stepPin;
this->dirPin = dirPin;
this->hallPin = hallPin;
stepper = AccelStepper(AccelStepper::DRIVER, stepPin, dirPin);

// Set the maximum speed and acceleration
stepper.setMaxSpeed(STEPS_PER_REVOLUTION * 8); // Set the maximum speed in steps per second
stepper.setAcceleration(STEPS_PER_REVOLUTION); // Set the acceleration in steps per second squared
stepper.setMaxSpeed(STEPS_PER_REVOLUTION * 2);
stepper.setAcceleration(STEPS_PER_REVOLUTION * 2);
}

void init()
{
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
pinMode(hallPin, INPUT_PULLUP);

digitalWrite(dirPin, HIGH); // Enables the motor to move in a particular direction

this->home();
}

void home()
{
// TODO: implement homing sequence
// TODO: make this non blocking by adding module states
Serial.println("Homing");
stepper.setSpeed(1000); // Steps per second
while (digitalRead(hallPin) == HIGH)
{
stepper.runSpeed();
}
stepper.setCurrentPosition(0);

// TODO: add max steps
}

void update()
{
// if (current pos % flapSteps == 0) {
// stepper.stop(); // reset to prevent overflow
// }
// normalized step
uint16_t normalizedStep = stepper.currentPosition() % STEPS_PER_REVOLUTION;

// at first flap, 1 deg
if (normalizedStep == STEPS_PER_REVOLUTION / 360 && digitalRead(hallPin) == HIGH)
{
Serial.println("Missed steps");

// get the target flap index before resetting the position
const uint8_t targetFlapIndex = getTargetFlapIndex();

stepper.setSpeed(1000); // Steps per second
while (digitalRead(hallPin) == HIGH)
{
stepper.runSpeed();
}

// set position to the nearest full rotation (rounded down)
long offset = stepper.currentPosition() % STEPS_PER_REVOLUTION;
stepper.setCurrentPosition(stepper.currentPosition() - offset);

setFlap(targetFlapIndex);
}

stepper.run();
}

[[deprecated("Use setFlap() with numeric index instead")]]
void setCharacter(char c)
{
int targetIndex = getCharacterIndex(c);
setFlap(targetIndex);
}

void setFlap(int index)
/** move to a specific flap index */
void setFlap(uint8_t index)
{
if (index < 0 || index >= FLAP_COUNT)
if (index >= FLAP_COUNT)
{
Serial.printf("Invalid index: %d\n", index);
return;
}

int currentIndex = getFlapIndex();
int currentPosition = stepper.currentPosition();
const uint8_t currentIndex = getCurrentFlapIndex();
const long currentPosition = stepper.currentPosition();

int steps = index - currentIndex;
int16_t steps = index - currentIndex;

if (steps < 0)
{
Expand All @@ -75,50 +105,26 @@ class SplitFlap
stepper.moveTo(currentPosition + steps * FLAP_STEPS);
}

void moveFlaps(int steps)
/** move x amount of flaps */
void moveFlaps(long steps)
{
stepper.moveTo(stepper.currentPosition() + steps * FLAP_STEPS);
stepper.moveTo(stepper.targetPosition() + steps * FLAP_STEPS);
}

private:
int stepPin;
int dirPin;
int hallPin;
AccelStepper stepper;

// 26 ABCDEFGHIJKLMNOPQRSTUVWXYZ
// 10 0123456789
// 20 !@#$%^&*()_+{}|:<>?/.,;[]\\=-`~
// 1 █ (full block)
// 1 space

// "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789?!@#$%^&*()+:/.,=-`\" █
// ",.?!=/-+:$%()"

// ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+{}|:<>?/.,;[]\\=-`~"
// █

// const String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789?!@#$%^&*()+:/.,=-`\" █";
// "+-*!.#%@?,&': █"
// "?!@&()+-%$█*= "
// " █?!@%'+-=.,#:"

// TODO: maybe reuse 0 and o and 1 and i
// const String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789?!@#$%^&*()+:/.,=-`\" █";
// | is full block
// ?!@-=+&%$#.,:'
[[deprecated("Update character list")]]
const String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-:,.'%$@?!# █";

// "+-*!.#%@?,&': █"
// "?!@&()+-%$█*= "
// " █?!@%'+-=.,#:"
const uint8_t FLAP_COUNT = 50;
const uint16_t FLAP_STEPS = STEPS_PER_REVOLUTION / FLAP_COUNT;

// +-:,.'%$@?!# █

const String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-:,.'%$@?!# |";
// | is full block??
const int FLAP_COUNT = characters.length();
const int FLAP_STEPS = STEPS_PER_REVOLUTION / characters.length();

int getCharacterIndex(char c)
[[deprecated("Use setFlap() with numeric index instead")]]
uint8_t getCharacterIndex(char c)
{
int index = characters.indexOf(toUpperCase(c)); // toupper(c) ??
if (index == -1)
Expand All @@ -129,8 +135,15 @@ class SplitFlap
return index;
}

int getFlapIndex()
/** get the current flap index */
uint8_t getCurrentFlapIndex()
{
return stepper.currentPosition() / FLAP_STEPS % FLAP_COUNT;
}

/** get the target flap index */
uint8_t getTargetFlapIndex()
{
return stepper.targetPosition() / FLAP_STEPS % FLAP_COUNT;
}
};
Binary file removed motorMountTest.SLDPRT
Binary file not shown.
Binary file modified splitFlap.SLDASM
Binary file not shown.
Binary file removed splitFlapUniBody1.SLDASM
Binary file not shown.
75 changes: 74 additions & 1 deletion splitflap.code-workspace
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,78 @@
"path": "code/module"
}
],
"settings": {}
"settings": {
"files.associations": {
"algorithm": "cpp",
"array": "cpp",
"atomic": "cpp",
"cctype": "cpp",
"chrono": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"condition_variable": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"exception": "cpp",
"fstream": "cpp",
"functional": "cpp",
"initializer_list": "cpp",
"ios": "cpp",
"iosfwd": "cpp",
"istream": "cpp",
"iterator": "cpp",
"limits": "cpp",
"list": "cpp",
"map": "cpp",
"memory": "cpp",
"mutex": "cpp",
"new": "cpp",
"numeric": "cpp",
"optional": "cpp",
"ostream": "cpp",
"queue": "cpp",
"random": "cpp",
"ratio": "cpp",
"shared_mutex": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"string": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"thread": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"typeinfo": "cpp",
"unordered_map": "cpp",
"utility": "cpp",
"vector": "cpp",
"xfacet": "cpp",
"xhash": "cpp",
"xiosbase": "cpp",
"xlocale": "cpp",
"xlocinfo": "cpp",
"xlocnum": "cpp",
"xmemory": "cpp",
"xmemory0": "cpp",
"xstddef": "cpp",
"xstring": "cpp",
"xtr1common": "cpp",
"xtree": "cpp",
"xutility": "cpp",
"*.tcc": "cpp",
"unordered_set": "cpp",
"memory_resource": "cpp",
"iomanip": "cpp",
"cinttypes": "cpp"
}
}
}