Arduino powered diy sea sweep! Oscillating wavemaker diy!

rickyb

Community Member
View Badges
Joined
Feb 13, 2014
Messages
61
Reaction score
24
Location
Coppell, TX
Rating - 0%
0   0   0
Any updates on how well the servo's are performing? I search the web and found some Heavy Duty/waterproof; would they work?
 
OP
OP
mstockmaster

mstockmaster

Active Member
View Badges
Joined
Mar 6, 2017
Messages
318
Reaction score
285
Location
Columbus Ohio
Rating - 0%
0   0   0
Any updates on how well the servo's are performing? I search the web and found some Heavy Duty/waterproof; would they work?
Sorry I haven't been on here in forever. Having a baby along with other hobbies and projects have kinda pushed the tank to the back burner. Plus my t5 fell in the tank a few months ago causing a slow crash. So I'm about to tear it down and start fresh. But, to answer the question, yes the servo is still running. You can definitely tell that it's wearing out because its no longer a smooth sweep all the time, there are some dead spots for sure. But it's been running 24/7 for the past 977 days straight with no real issues, assuming a sweep takes 15 seconds that's over 5.5 million sweeps, which I'd say is pretty great. I honestly didn't think the servo would last a year.
 

rickyb

Community Member
View Badges
Joined
Feb 13, 2014
Messages
61
Reaction score
24
Location
Coppell, TX
Rating - 0%
0   0   0
Congratulations!!!

I did some research and found another board that can be used for this purpose and build my own. So far they been running close to a year but depending on pump speed they can be a little noisy. One of the servos bottom shaft is faulty (not the same as listed here). I’m in the process of replacing them but this time I’m going to place them with gear down.

98DFAC46-AD3B-4EBB-85B5-0171CEBD9C90.jpeg
 

Macca_75

Active Member
View Badges
Joined
Jan 31, 2019
Messages
369
Reaction score
166
Rating - 0%
0   0   0
You've inspired me - I have an UNO lying around. I also have one of these brackets I bought years ago (was building something similar using PICAXE - but never finished it.

I also have a bracket I bought online that is purpose built for DIY sea sweeps and takes the Futaba servo's - https://neo3plus.com/en/accessoires/203-osmolateur-digiosmo.html
 
Last edited:

Macdaddynick1

Valuable Member
View Badges
Joined
May 20, 2014
Messages
1,790
Reaction score
2,299
Location
Reseda, California
Rating - 0%
0   0   0
Congratulations!!!

I did some research and found another board that can be used for this purpose and build my own. So far they been running close to a year but depending on pump speed they can be a little noisy. One of the servos bottom shaft is faulty (not the same as listed here). I’m in the process of replacing them but this time I’m going to place them with gear down.

98DFAC46-AD3B-4EBB-85B5-0171CEBD9C90.jpeg
What board did you use?
 

Brian S

Community Member
View Badges
Joined
Oct 26, 2017
Messages
77
Reaction score
20
Rating - 0%
0   0   0
Any details on why you have selected this specific servo? What makes this one special over others?
 

Brian S

Community Member
View Badges
Joined
Oct 26, 2017
Messages
77
Reaction score
20
Rating - 0%
0   0   0
Thanks!

I ordered the below servo - the waterproof sold me. Will it work?


ANNIMOS 20KG RC Servo Digital High Torque Full Metal Gear Waterproof,180° Control Angle

 

rickyb

Community Member
View Badges
Joined
Feb 13, 2014
Messages
61
Reaction score
24
Location
Coppell, TX
Rating - 0%
0   0   0
Thanks!

I ordered the below servo - the waterproof sold me. Will it work?


ANNIMOS 20KG RC Servo Digital High Torque Full Metal Gear Waterproof,180° Control Angle


The ones I ordered are dual shaft and come with brackets,FYI
 

Macca_75

Active Member
View Badges
Joined
Jan 31, 2019
Messages
369
Reaction score
166
Rating - 0%
0   0   0
Is this sold by anyone in the US?
I'm actually in Australia, but just bought in online.

Anyway I found an old Ardunio lying around and made a prototype. So far I have a setup routine that allows you to use encoder to set left and right swing points and a routine to manually "point" the servo with the encoder. Just need to write the routine to "swing" the pump and connect a 3 way switch.
 

Macca_75

Active Member
View Badges
Joined
Jan 31, 2019
Messages
369
Reaction score
166
Rating - 0%
0   0   0
This is my first go at Arduino so hopefully some pro's can help fix my code (seems to be working but I am sure it's far from best practice).

I've also reused bits of code from all over the internet, but found this guys Youtube channel great - https://www.youtube.com/channel/UC8z5SHQhi9veBOAaFPZffNA (a lot of my code started from his)

Any, as a description. I have a rotary encoder with push button (represented in the Fritz as 2 separate components), a 1 pole, 12 way rotary switch (set to 4 positions only), a servo (Futuba as it fits the bracket I have and is cheap to replace if it doesn't last) and some LED's (blue/white which work with encoder and 4 x green with indicate he position of the rotary switch).

Switch Position 1:
Use the rotary encoder to move the servo left/right. Push button stores the position and moves the servo to the other (ie. move it to left position, push button, left limit is stored and servo moves to right stored position. Move servo to right limit, push button and it stores the position and switches back to the left stored position).

Switch Position 2:
Servo moves according to rotary encoder. Push button does nothing.

Switch Position 3:
Servo sweeps from left position to right position to left position, to right position and so on. Pressing and holding the encoder button pauses the servo and allows you to speed up or slow down (adjust) the speed of the sweep.

Switch Position 4:
Saved for future. Thinking maybe uses the left and right positions, but uses a random sweep speed that changes every time. Open to other possibilities.

The Fritz diagram (once again my first go at it - I couldn't get it to look as neat as I wanted.)

1604309585232.png


The code

Code:
/* Need to do the following
 *  Need to store setpoint[1] & setpoint[2] and sweep_array[sweep_delay] values in EEPROM in case of power outage
 *  and read them back on boot
 */
#include <Servo.h>
//#include <EEPROM.h>

// define pins to be used
#define ENC_SW_PIN      2
#define SERVO_PIN       3
#define ENC_DATA_PIN    4
#define ENC_CLK_PIN     5
#define LEFT_LED        6
#define RIGHT_LED       7
#define LED_1           8
#define LED_2           9
#define LED_3           10
#define LED_4           11
#define SW_ROT1         22
#define SW_ROT2         24
#define SW_ROT3         26
#define SW_ROT4         28

//define variables
#define INCREMENT       1
#define SWEEP_INCREMENT 10
#define SERVO_INTERVAL  5  //ms between servo steps
#define MIN_ANGLE       5
#define MAX_ANGLE       175
#define MIN_SWEEP       50
#define MAX_SWEEP       500

byte sweep_delay;
byte enc_clk,    enc_clk_old;
byte enc_switch, enc_switch_old;
byte pointer; // pointer to setpoint[pointer]
int angle = (MIN_ANGLE + MAX_ANGLE) / 2;
int setpoint[2] = {angle, angle + 10}; //startup angles
int sweep_array[1] = {sweep_delay};
unsigned long timeforservo;
Servo servo;

void setup() { 
  pinMode (ENC_CLK_PIN,INPUT_PULLUP);
  pinMode (ENC_DATA_PIN,INPUT_PULLUP);
  pinMode (ENC_SW_PIN,INPUT_PULLUP);
  pinMode (LEFT_LED, OUTPUT);
  pinMode (RIGHT_LED, OUTPUT);
  pinMode (SW_ROT1,INPUT_PULLUP);
  pinMode (SW_ROT2,INPUT_PULLUP);
  pinMode (SW_ROT3,INPUT_PULLUP);
  pinMode (SW_ROT4,INPUT_PULLUP);
  pinMode (LED_1,OUTPUT);
  pinMode (LED_2,OUTPUT);
  pinMode (LED_3,OUTPUT);
  pinMode (LED_4,OUTPUT);
  servo.attach(SERVO_PIN);
  Serial.begin (9600);
  enc_clk_old    = digitalRead(ENC_CLK_PIN);
  enc_switch_old = digitalRead(ENC_SW_PIN);
  sweep_array[sweep_delay] = 50;
}

void loop() {
  digitalRead (SW_ROT1);
  digitalRead (SW_ROT2);
  digitalRead (SW_ROT3);
  digitalRead (SW_ROT4);

// THIS IS USED TO SET MIN AND MAX IN SETUP MODE

  if (digitalRead (SW_ROT1) == 0) {
//    Serial.println ("Setup Mode selected");
    digitalRead (SW_ROT1);
    digitalWrite (LED_1, HIGH);
    digitalWrite (LED_2, LOW);
    digitalWrite (LED_3, LOW);
    digitalWrite (LED_4, LOW);
    enc_switch = digitalRead(ENC_SW_PIN);
    if((enc_switch == 0) && (enc_switch_old == 1)) { // 1->0 transition detected
      pointer = (pointer + 1) % 2; // change servo setpoint 
      Serial.print("SETPOINT is ");
      Serial.print(angle);
      Serial.print(", Min Angle is currently ");
      Serial.print(setpoint[0]);
      Serial.print(", Max Angle is currently ");
      Serial.println(setpoint[1]);
      delay(50);
      if (angle < setpoint[pointer]) {
        digitalWrite (LEFT_LED, HIGH);
        digitalWrite (RIGHT_LED, LOW);
      } else {
        digitalWrite (LEFT_LED, LOW);
        digitalWrite (RIGHT_LED, HIGH);
      }
    }

    enc_switch_old = enc_switch;

// READ ROTARY AND MODIFY SERVO SETPOINT MIN, MAX 
   enc_clk = digitalRead(ENC_CLK_PIN);
   if((enc_clk == 1) && (enc_clk_old == 0)) { // 0->1 transition
    if(digitalRead(ENC_DATA_PIN) == 1) {
      setpoint[pointer] = setpoint[pointer] + INCREMENT;
      } else {
        setpoint[pointer] = setpoint[pointer] - INCREMENT;
      }
    if((setpoint[pointer] > MAX_ANGLE) && (angle > setpoint [0])) setpoint[pointer] = MAX_ANGLE;
    if(setpoint[pointer] < MIN_ANGLE) setpoint[pointer] = MIN_ANGLE;
    Serial.println(angle);
    delay(10);
  }
  enc_clk_old = enc_clk;

// ROTATE SERVO
  if (millis() > timeforservo) {
    timeforservo = millis() + SERVO_INTERVAL;
    if (angle < setpoint[pointer]) {
      angle++;
    }
    if (angle > setpoint[pointer]) {
      angle--;
    }
    servo.write(angle);
  }
}

// THIS IS USED TO MOVE SERVO MANUALLY

if (digitalRead (SW_ROT2) ==0) {
  digitalRead (SW_ROT2);

    digitalWrite (LED_1, LOW);
    digitalWrite (LED_2, HIGH);
    digitalWrite (LED_3, LOW);
    digitalWrite (LED_4, LOW);
    
// READ ROTARY AND MODIFY SERVO SETPOINT MIN, MAX 
  enc_clk = digitalRead(ENC_CLK_PIN);
  if((enc_clk == 1) && (enc_clk_old == 0)) { // 0->1 transition
    if(digitalRead(ENC_DATA_PIN) == 1) {
      setpoint[pointer] = setpoint[pointer] + INCREMENT;
      digitalWrite (LEFT_LED, LOW);
      digitalWrite (RIGHT_LED, HIGH);
    }
    else {
      setpoint[pointer] = setpoint[pointer] - INCREMENT;
      digitalWrite (LEFT_LED, HIGH);
      digitalWrite (RIGHT_LED, LOW);
      }
    if(setpoint[pointer] > MAX_ANGLE) setpoint[pointer] = MAX_ANGLE;
    if(setpoint[pointer] < MIN_ANGLE) setpoint[pointer] = MIN_ANGLE;
    Serial.println(setpoint[pointer]);
    delay(10);
  }
  enc_clk_old = enc_clk;

// ROTATE SERVO
  if (millis() > timeforservo) {
    timeforservo = millis() + SERVO_INTERVAL;
    if (angle < setpoint[pointer]) angle++;
    if (angle > setpoint[pointer]) angle--;
    servo.write(angle);
  }
}

// THIS IS USED TO SWEEP FROM LEFT TO RIGHT AND BACK

if (digitalRead (SW_ROT3) == 0) {
//  THIS CODE BELOW IS USED TO SWEEP

    digitalWrite (LED_1, LOW);
    digitalWrite (LED_2, LOW);
    digitalWrite (LED_3, HIGH);
    digitalWrite (LED_4, LOW);
    
  Serial.println ("Sweep Mode selected");
  Serial.print ("Encoder Switch pin is ");
  Serial.println (digitalRead (ENC_SW_PIN));
  Serial.print ("Sweep Speed is ");
  Serial.println (sweep_array[sweep_delay]);
  if (digitalRead (ENC_SW_PIN) == HIGH) {
    for (angle = setpoint[0]; angle <= setpoint[1]; angle += 1) { // goes from MIN_ANGLE to MAX_ANGLE in increments of 1 degree
//    for (angle = MIN_ANGLE; angle <= MAX_ANGLE; angle += 1) { // goes from MIN_ANGLE to MAX_ANGLE in increments of 1 degree
  // LED's configured for left sweep
      digitalWrite (LEFT_LED, HIGH);
      digitalWrite (RIGHT_LED, LOW);
      servo.write(angle);              // tell servo to go to position 'angle'
      delay(sweep_array[sweep_delay]);                       // waits for servo delay
      digitalRead (SW_ROT3);
      digitalRead (ENC_SW_PIN);                             // Reads encoder switch pin looking for press
      while (digitalRead (ENC_SW_PIN) == LOW) {
  // LED's both on to indicate speed configuration
        digitalWrite (LEFT_LED, HIGH);
        digitalWrite (RIGHT_LED, HIGH);
        enc_clk = digitalRead(ENC_CLK_PIN);
        if((enc_clk == 1) && (enc_clk_old == 0)) { // 0->1 transition
          if(digitalRead(ENC_DATA_PIN) == 1) sweep_array[sweep_delay] = sweep_array[sweep_delay] + SWEEP_INCREMENT;
            else sweep_array[sweep_delay] = sweep_array[sweep_delay] - SWEEP_INCREMENT;
            if(sweep_array[sweep_delay] > MAX_SWEEP) sweep_array[sweep_delay] = MAX_SWEEP;
            if(sweep_array[sweep_delay] < MIN_SWEEP) sweep_array[sweep_delay] = MIN_SWEEP;
            Serial.print ("Sweep Delay is ");
            Serial.println(sweep_array[sweep_delay]);
            delay(10);
        }
        enc_clk_old = enc_clk;
      }
    }
    Serial.println ("Finished MIN to MAX angle sweep");
    for (angle = setpoint[1]; angle >= setpoint[0]; angle -= 1) { // goes from 180 degrees to 0 degrees  
//    for (angle = MAX_ANGLE; angle >= MIN_ANGLE; angle -= 1) { // goes from 180 degrees to 0 degrees
  // LED's configured for right sweep
      digitalWrite (LEFT_LED, LOW);
      digitalWrite (RIGHT_LED, HIGH);
      servo.write(angle);              // tell servo to go to position in variable 'point of sale'
      delay(sweep_array[sweep_delay]);                       // waits 15ms for the servo to reach the position
      digitalRead (ENC_SW_PIN);
      while (digitalRead (ENC_SW_PIN) == LOW) {
  // LED's both on to indicate speed configuration
        digitalWrite (LEFT_LED, HIGH);
        digitalWrite (RIGHT_LED, HIGH);
        enc_clk = digitalRead(ENC_CLK_PIN);
        if((enc_clk == 1) && (enc_clk_old == 0)) { // 0->1 transition
          if(digitalRead(ENC_DATA_PIN) == 1) sweep_array[sweep_delay] = sweep_array[sweep_delay] + SWEEP_INCREMENT;
            else sweep_array[sweep_delay] = sweep_array[sweep_delay] - SWEEP_INCREMENT;
            if(sweep_array[sweep_delay] > MAX_SWEEP) sweep_array[sweep_delay] = MAX_SWEEP;
            if(sweep_array[sweep_delay] < MIN_SWEEP) sweep_array[sweep_delay] = MIN_SWEEP;
            Serial.print ("Sweep Delay is ");
            Serial.println(sweep_array[sweep_delay]);
            delay(10);
          }
          enc_clk_old = enc_clk;
        }
      }
    }
  }

// THIS IS RESERVED - MAYBE FOR RANDOM SWEEP SPEED - CURRENTLY BLINKS LEDS
if (digitalRead (SW_ROT4) == LOW){
  Serial.println ("Mode 4 selected");

    digitalWrite (LED_1, LOW);
    digitalWrite (LED_2, LOW);
    digitalWrite (LED_3, LOW);
    digitalWrite (LED_4, HIGH);
    
  digitalWrite (LEFT_LED, LOW);
  digitalWrite (RIGHT_LED, HIGH);
  delay (100);
  digitalWrite (LEFT_LED, HIGH);
  digitalWrite (RIGHT_LED, LOW);
  delay (100);
  digitalRead (SW_ROT4);
  }
}

And forgive me for the crude video but here is a quick demo of it in action (the screeching of the servo is much worse in the video than in real life). First switch position was 1 (setting left and right limits), 2nd was "manually" pointing it, 3rd was a sweep from left -> right -> left (including adjusting the sweep speed - I think I need to reverse the up vs down direction for sweep speed) and 4th is just flashing lights at this stage.

















Please feel free to suggest any improvements.
 

AlexG

Valuable Member
View Badges
Joined
Jun 20, 2013
Messages
2,112
Reaction score
4,898
Location
Illinois
Rating - 0%
0   0   0
This thread has got me thinking I will do something similar but instead of a servo I would use a stepper motor and some linkage to control the sweep of a powerhead.
 

Derek4real

Community Member
View Badges
Joined
Dec 13, 2012
Messages
26
Reaction score
24
Location
Dallas
Rating - 0%
0   0   0
Aquatic Life made these few years ago at a very affordable price.



I just recently bought one, I have yet to put it on my tank.

I also do have the OG SeaSwirls on the bigger tank.
 

Macca_75

Active Member
View Badges
Joined
Jan 31, 2019
Messages
369
Reaction score
166
Rating - 0%
0   0   0
Aquatic Life made these few years ago at a very affordable price.



I just recently bought one, I have yet to put it on my tank.

I also do have the OG SeaSwirls on the bigger tank.

Not quite the same - the aquatic life one doesn't move an existing powerhead. I already have the Tunze 6105's in the tank (near a corner). I want to make it swirl.

Plus who doesn't like a bit of DIY.

For me the hardware is almost as much of a challange (enjoyment) as the tank itself.
 

Macca_75

Active Member
View Badges
Joined
Jan 31, 2019
Messages
369
Reaction score
166
Rating - 0%
0   0   0
I am thinking I will add another switch position and take a 1-10v input from a controller (I happen to use Profilux). That way I can set the 1-10v port up as a stream pump on wave mode. instead of ramping the pump up and down 0v will be left position, 10v will be right position.

Don't think it will add value - just something else to add. it's only really 2 resistors (so I can split the 10v into 0-5v and plug it into an ADC on the Arduino.
 

Derek4real

Community Member
View Badges
Joined
Dec 13, 2012
Messages
26
Reaction score
24
Location
Dallas
Rating - 0%
0   0   0
Not quite the same - the aquatic life one doesn't move an existing powerhead. I already have the Tunze 6105's in the tank (near a corner). I want to make it swirl.

Plus who doesn't like a bit of DIY.

For me the hardware is almost as much of a challange (enjoyment) as the tank itself.

thats understandable. the price of the seasweeps are stupid crazy. Plus I have several older older tunzes i would like to put to use.
 

Reefing threads: Do you wear gear from reef brands?

  • I wear reef gear everywhere.

    Votes: 30 15.8%
  • I wear reef gear primarily at fish events and my LFS.

    Votes: 11 5.8%
  • I wear reef gear primarily for water changes and tank maintenance.

    Votes: 1 0.5%
  • I wear reef gear primarily to relax where I live.

    Votes: 25 13.2%
  • I don’t wear gear from reef brands.

    Votes: 111 58.4%
  • Other.

    Votes: 12 6.3%
Back
Top