Bom, não tenho formação universitária mas aprendo rápido. Estou montando meu primeiro marinho, comprei leds da rapidleds com controladora PWM 0-10v e estou usando uma protoboard aqui para fazer os LEDs acenderem(com trânsistor para fazer o level shift de 5v para 10v). Ta muito feio e to com vergonha de colocar a foto aqui.
Principalmente lá fora, tem diversas controladoras para aquário open source/hardware, entretanto nunca vi uma nacional e boa o suficiente para as minhas necessidades. Comecei a bolar uma, peguei coisas da Typhon, coisas do ReefAngel e assim vou montando minha controladora frankenstein.
Por enquanto o esquema dela está abaixo:
Como ainda está em fase de desenvolvimento, ainda não tem github nem nada, mais para frente quando estiver maduro o suficiente eu crio o repositório.
Features do hardware:
- baseado no atmega328p(arduino uno, ...)
- porta ISP para gravar bootloader se necessário e porta FTDI para fazer upload dos códigos
- 4 canais de controle de LED PWM 0-10v
- 1 canal PWM de Cooler com controle de RPM
- RTC DS3231 - é o mais preciso que eu tinha por aqui
- LCD de 4x20 I2C
TODO:
- mudar os canais de LED para ser igual do typhon para escolher 0-10v, PWM 0-5v e PWM 0-10v
- estudar porque o reefangel usa opamp para aumentar o PWM de 5v para 10v ao invés de trânsistor(de repente a velocidade do PWM, o trânsistor não aguenta), mas sei lá, é só suposição, preciso estudar para ver o que vamos usar
- canal one-wire para colocar sensores de temperatura
- XBee / Rede: eu particularmente uso XBee aqui em casa para alguns trecos que eu fiz aqui, e vou implementar ele na placa. mas posso estudar se alguém tiver algum esquema bom para fazer uma interface de rede ou rede sem fio para ele
- se for para SMD, vou mudar o atmega328p para o atmega2560... tenho conhecimentos de ARM, e também poderia fazer com STM32F1xx ou F40x, mas aí é tudo 3.3v, e vai precisar mudar bastante coisa. também ficaria mais dificil mecher no software por que fica mais distante do público em geral e não quero que o software fique 100% dependente de mim
Software que estou usando para testar. Eu não gosto da maneira arduino de programar(tudo no loop), então estou fazendo o código emulando um RTOS via millis().
Código: Selecionar todos
#include <SerialCommand.h>
#include <Wire.h>
#include <Time.h>
#include <LiquidCrystal_I2C.h>
#include <DS3232RTC.h>
#define blueLEDPin 3 // channel 1
#define colorLEDPin 5 // channel 2
#define whiteLEDPin 6 // channel 3
#define uvLEDPin 9 // channel 4
#define fanPin 10
#define fanSpeedPin 2
volatile unsigned long counter = 0;
volatile unsigned long result = 0;
unsigned long clockDelay = 1000;
unsigned long fanRpmDelay = 1000;
unsigned long setLedBrightnessDelay = 200;
unsigned long clockWait = clockDelay;
unsigned long fanRpmWait = fanRpmDelay;
unsigned long setLedBrightnessWait = setLedBrightnessDelay;
LiquidCrystal_I2C lcd(0x20, 20, 4);
SerialCommand SCmd;
void rpmCount() {
counter++;
}
ISR(TIMER1_COMPA_vect) {
result = (counter / 2) * 60;
counter = 0;
}
#include <stdarg.h>
void lcdprintf(char *fmt, ... ){
char tmp[128]; // resulting string limited to 128 chars
va_list args;
va_start (args, fmt );
vsnprintf(tmp, 128, fmt, args);
va_end (args);
lcd.print(tmp);
}
void setLEDChannelBrightness(uint8_t channel, uint16_t value) {
switch (channel) {
case 1:
analogWrite(blueLEDPin, value);
lcd.setCursor(5, 1);
break;
case 2:
analogWrite(colorLEDPin, value);
lcd.setCursor(16, 1);
break;
case 3:
analogWrite(whiteLEDPin, value);
lcd.setCursor(5, 2);
break;
case 4:
analogWrite(uvLEDPin, value);
lcd.setCursor(16, 2);
break;
}
lcdprintf("%3d", value);
}
void setFanSpeed(uint16_t value) {
analogWrite(fanPin, value);
lcd.setCursor(5, 3);
lcdprintf("%3d", value);
}
void calcAndShowFanSpeed() {
lcd.setCursor(16, 3);
lcdprintf("%4ld", result);
}
void setup() {
Serial.begin(115200);
setSyncProvider(RTC.get);
if (timeStatus() != timeSet)
Serial.println("Unable to sync with the RTC");
else
Serial.println("RTC has set the system time");
SCmd.addCommand("SET_TIME",set_time);
SCmd.addDefaultHandler(unrecognized);
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 1);
lcd.print(" Welcome to");
lcd.setCursor(0, 2);
lcd.print(" TrunetReef");
delay(3000);
lcd.clear();
lcd.print("TrunetReef");
lcdprintf(" %02d:%02d:%02d", hour(), minute(), second());
lcd.setCursor(0, 1);
lcd.print("CH1: 0 | CH2: 0");
lcd.setCursor(0, 2);
lcd.print("CH3: 0 | CH4: 0");
lcd.setCursor(0, 3);
lcd.print("FAN: 0 | RPM: 0");
setLEDChannelBrightness(1, 0);
setLEDChannelBrightness(2, 128);
setLEDChannelBrightness(3, 255);
setLEDChannelBrightness(4, 0);
cli();
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 15624; //(16*10^6) / (1024 * 1) -1
TCCR1B |= (1 << WGM12);
TCCR1B |= (1 << CS12) | (1 >> CS10);
TIMSK1 |= (1 << OCIE1A);
sei();
pinMode(fanSpeedPin, INPUT);
attachInterrupt(0, rpmCount, RISING);
setFanSpeed(255);
}
uint16_t i = 0;
void loop() {
// Serial Read
SCmd.readSerial();
// thread 1 - set brightness on ch1
if ((long)(millis() - setLedBrightnessWait)>=0) {
setLEDChannelBrightness(1, i);
if (i < 255) {
i += 5;
} else {
setLedBrightnessWait += 3000;
i = 0;
}
setLedBrightnessWait += setLedBrightnessDelay;
}
// thread 2 - Fan Speed Update
if ((long)(millis() - fanRpmWait)>=0) {
calcAndShowFanSpeed();
fanRpmWait += fanRpmDelay;
}
// thread 3 - Clock Update
if ((long)(millis() - clockWait)>=0) {
lcd.setCursor(12, 0);
lcdprintf("%02d:%02d:%02d", hour(), minute(), second());
clockWait += clockDelay;
}
}
void unrecognized() {
Serial.println("Unrecognized command!");
}
void set_time () {
char *arg;
time_t t;
tmElements_t tm;
arg = SCmd.next();
if (arg != NULL) {
time_t t = atol(arg);
if (t > 0) {
RTC.set(t); // set the RTC and the system time to the received value
setTime(t);
}
}
}
Gostaria de sugestões para o que eu poderia incorporar na placa. Estou pensando em fazer um "run" de umas 10 placas na china com a placa 100% montada se arrumar gente para rachar comigo. Então, vou usar componentes SMD, mas posso manter trough-hole se a maioria preferir assim, entretanto alguns componentes que quero colocar(por exemplo DS3231), é só SMD.