Re: Узел отбора на перистальтическом насосе
хоть и дороже чем кран
Чем кран и клапан. А может и не дороже.
Форум самогонщиков, винокуров, виноделов, пивоваров, бондарей и очень хороших людей |
Назад 1 … 12 13 14 15 16 … 53 Следующая
Чтобы отправить ответ, вы должны войти или зарегистрироваться
с 261 по 280 из 1 059
хоть и дороже чем кран
Чем кран и клапан. А может и не дороже.
Чем кран и клапан. А может и не дороже.
А если посчитать сборку управления клапаном, то не дороже.
Вообщем надо тему оформлять.
Сам скетч без изменений
Предложение автору: управление по i2c(на рассмотрение)
переносим переменные в структуру
typedef struct
{
uint16_t rate; //int16 - не думаем про выравнивание в памяти(+1 байт)
uint16_t drinkVolume = 0; // Шаг рОзлива
uint16_t totalVolume = 0; // Общий объем отбора мл
uint16_t currentMode;
}slave_data_t;
//команда от мастера
typedef struct
{
uint16_t cmd;//int16...выравнивание
uint16_t val;
}master_cmd_t;
#define I2C_ADDR (0x1e) //наш адрес
slave_data_t dz;
void requestEvent(){
//все данные в структуре, просто выдаем...
Wire.write((uint8_t*)&dz,sizeof(dz));
}
//пару дефайнов
#define SET_RATE 21 //
#define CLEAR_COUNTERS 22 //
//Аля модбус
void receiveEvent(int howMany) {
master_cmd_t cmd;
uint8_t data[howMany];
int x=0;
while (Wire.available()>0) { // loop through all but the last
data[x] = Wire.read(); // receive byte as a character
x++;
}
if ((howMany)==sizeof(cmd)){
memcpy(&cmd,&data,sizeof(cmd));
switch (cmd.cmd){
case RUNNING:{
resumeRun();
}
break;
case PAUSED_BY_EXT:{
dz.currentMode = cmd.cmd;
}
break;
case SELECT_VOL:{
dz.drinkVolume=cmd.val;
drinkBackCounter = (uint32_t)dz.drinkVolume * stepsForOneMl - 1;
}
break;
case CLEAR_COUNTERS:{
stepsCount = 0;
dz.totalVolume = 0;
drinkBackCounter = (uint32_t)dz.drinkVolume * stepsForOneMl - 1;
}
break;
case SET_RATE:{
if (cmd.val>maximumRate)dz.rate=maximumRate;
else dz.rate=cmd.val;
calcOCR1A();
resumeRun();
}
break;
}
}
calcTotalVolume();
//все данные в структуре, заносить ничего не надо
}
void setup()
{
Wire.begin(I2C_ADDR);
Wire.onRequest(requestEvent);
Wire.onReceive(receiveEvent);
//...
}
Забыл, есть проблема, слетает слейв адрес.
Кто портит регистр TWAR - не нашел.
Временный костыль:
#define TWI_SA (I2C_ADDR<<1)
//проверяем в loop
void loop()
{
if (TWAR!=TWI_SA) TWAR=TWI_SA;
///...
}
Предложение автору: управление по i2c(на рассмотрение)
А что там рассматривать ?
Лично я приветствую.
Ибо:
Всё на свой страх и риск с осознанием возможных последствий.
Так же всё отдаётся в свободное использование и модификацию.
Только просьба модифицированный скетч выкладывать целиком.
С описанием изменений.
Ну и внесения в аппаратную часть, если есть, тоже публиковать.
Чтобы любой заинтересовавшийся мог повторить всё это по возможности без плясок с бубном.
Только просьба модифицированный скетч выкладывать целиком.
Внимание!!!Пины переназначены
#include <EEPROM.h> // Стандартная библиотека
#include "GyverEncoder.h" // Библиотеки с сайта
#include "GyverTM1637.h" // не могу публиковать ссылки
#include "directTimers.h" //не могу публиковать ссылки
#include "Wire.h"
#include <avr/wdt.h>
//------------------------------------------------------------------------------------------
//**********************************************************************************************************
#define STEP8 // Закомментировать, если используется шаг/4, раскомментировать, если используется шаг/8 *
//**********************************************************************************************************
//--------------------------- Настройка железа ---------------------------------------------
// Подключение энкодера
#define SW1 A2 // Сигнал энкодера 1 // Если кручение влево/вправо перепутано,
#define SW2 A1 // Сигнал энкодера 2 // можно поменять местами или изменить сигнал DIR на DRV8825
#define KEY A3 // Кнопка энкодера
Encoder enc1(SW1, SW2, KEY, TYPE1);
// Подключение TM1637
#define CLK 13 // Тактовые импульсы TM1637
#define DIO 12 // Данные для TM1637
GyverTM1637 disp(CLK, DIO);
// Подключение DRV8825
#define STEP 2 // Тактовые импульсы на драйвер ШД
// Внешнее управление
#define TMAS 5 // Сюда подключаем управление от TMAS, низкий уровень вызовет паузу
#define LED 13 // Встроенный светодиод
#define PIEZO 11
#define soundA B00000101
#define soundB B00011111
//--------------------------------------------------------------------------------------
// Наименования режимов работы
//----------------------------------------------
#define RUNNING 0 //
#define PAUSED 1 //
#define PAUSED_BY_EXT 2 //
#define PAUSED_BY_VOL 3 //
#define SELECT_VOL 4 //
#define TUNING 10 //
#define TUNING_PAUSE 11 //
#define SET_RATE 21 //
#define CLEAR_COUNTERS 22 //
//----------------------------------------------
// Константы
//----------------------------------------------
#define maximumRate 2500 // Максимальная скорость отбора мл/час
#define rateStep 10 // Мелкий шаг регулировки отбора
#define rateMidStep 50 // Средний шаг регулировки отбора
#define rateBigStep 100 // Крупный шаг регулировки отбора
#define volStep 10 // Шаг регулировки дозатора
#define volMidStep 50 // Средний шаг регулировки дозатора
#define volBigStep 500 // Крупный шаг регулировки дозатора
#define maxDrinkVol 5000 // Максимальный объем, выдаваемый дозатором
#define defaultDrink 0 // Объем дозатора по умолчанию. 0 - без ограничения.
#define defaultStepsFor100ml 400000 // Количество шагов потребное для отбора 100 мл по умолчанию при шаге/4
#define minStepsFor100ml 150000 // Минимально возможное число шагов для отбора 100 мл при шаге/4
#ifdef STEP8
#define defaultStepsFor100ml 800000 // Количество шагов потребное для отбора 100 мл по умолчанию при шаге/8
#define minStepsFor100ml 550000 // Минимально возможное число шагов для отбора 100 мл при шаге/8
#endif
//----------------------------------------------
// Переменные
//----------------------------------------------
unsigned long stepsFor100ml; // Количество шагов потребное для отбора 100 мл
unsigned int stepsForOneMl; // Количество шагов потребное для отбора 1 мл
unsigned long stepsCount = 0; // Счетчик количества шагов
unsigned long drinkBackCounter = 0; // Обратный счётчик шагов дозатора
unsigned long temp = 0; // Временная переменная для разнообразных нужд
unsigned int timer1EndValue = 65535; // Значение при котором происходит прерывание от таймера 1 (11739)
byte thousandth = 0; //
byte tenth = 0; //
byte backCounter0 = 0; //
byte backCounter1 = 0; //
byte counterA = 0; //
//byte currentMode = RUNNING; // Текущий режим работы
byte pattern = 0; //
//int rate = 0; // Скорость отбора мл/час 0 - maximumRate
//int totalVolume = 0; // Общий объем отбора мл
//int drinkVolume = 0; // Шаг рОзлива
bool newSecond = false;
bool newTenth = false;
bool stepEnabled = false;
bool tmasStop = false;
bool drinkStop = false;
bool infoEnable = false;
bool bc0flag = false;
bool bc1flag = false;
bool sndFlag = false;
//--------------------------------------------------------------------------------------
typedef struct
{
uint16_t rate;
uint16_t drinkVolume = 0; // Шаг рОзлива
uint16_t totalVolume = 0; // Общий объем отбора мл
uint16_t currentMode;
}slave_data_t;
typedef struct
{
uint16_t cmd;
uint16_t val;
}master_cmd_t;
void resumeRun();
void increaseRate();
void decreaseRate();
void calcOCR1A();
void calcTotalVolume();
void oneTenthSub();
void tryToSaveStepsFor100ml();
#define I2C_ADDR (0x1e)
#define TWI_SA (I2C_ADDR<<1)
slave_data_t dz;
/*
void set_var(){
dz.rate = 0; // Скорость отбора мл/час 0 - maximumRate
dz.totalVolume = 0; // Общий объем отбора мл
dzdrinkVolume = 0;
currentMode = RUNNING;
}
*/
void requestEvent(){
Wire.write((uint8_t*)&dz,sizeof(dz));
}
void receiveEvent(int howMany) {
master_cmd_t cmd;
uint8_t data[howMany];
int x=0;
while (Wire.available()>0) { // loop through all but the last
data[x] = Wire.read(); // receive byte as a character
x++;
}
if ((howMany)==sizeof(cmd)){
memcpy(&cmd,&data,sizeof(cmd));
switch (cmd.cmd){
case RUNNING:{
resumeRun();
}
break;
case PAUSED_BY_EXT:{
dz.currentMode = cmd.cmd;
}
break;
case SELECT_VOL:{
dz.drinkVolume=cmd.val;
drinkBackCounter = (uint32_t)dz.drinkVolume * stepsForOneMl - 1;
}
break;
case CLEAR_COUNTERS:{
stepsCount = 0;
dz.totalVolume = 0;
drinkBackCounter = (uint32_t)dz.drinkVolume * stepsForOneMl - 1;
}
break;
case SET_RATE:{
if (cmd.val>maximumRate)dz.rate=maximumRate;
else dz.rate=cmd.val;
calcOCR1A();
resumeRun();
}
break;
}
}
calcTotalVolume();
}
void setup()
{
Wire.begin(I2C_ADDR);
Wire.onRequest(requestEvent);
Wire.onReceive(receiveEvent);
Wire.setTimeout( 500 );
Serial.begin(115200);
// Настройка входов и выходов
pinMode(STEP, OUTPUT);
pinMode(CLK, OUTPUT);
pinMode(DIO, OUTPUT);
pinMode(LED, OUTPUT);
pinMode(PIEZO, OUTPUT);
pinMode(SW1, INPUT_PULLUP);
pinMode(SW2, INPUT_PULLUP);
pinMode(KEY, INPUT_PULLUP);
pinMode(TMAS, INPUT_PULLUP);
digitalWrite(STEP, 1);
digitalWrite(PIEZO, 1);
// Настройка таймера 1, он задаёт частоту шагания двигателя
TIMER1_setClock(PRESCALER_64); // Частота тактирования таймера 1: 16/64 = 0.25 МГц при шаге/4
#ifdef STEP8
TIMER1_setClock(PRESCALER_8); // Частота тактирования таймера 1: 16/8 = 2 МГц при шаге/8
#endif
TIMER1_setMode(CTC_MODE); // Режим работы таймера - сравнение со значением, прерывание и рестарт
TIMER1_COMPA_setValue(timer1EndValue); // Значение для сравнения
TIMER1_attach_COMPA(); // Прерывание от таймера 1 по сравнению
// Настройка таймера 2, он отсчитывает временные интервалы для работы программы
TIMER2_setClock(PRESCALER_128); // Частота тактирования таймера 2: 16/128 = 0.125 МГц
TIMER2_setMode(CTC_MODE); // включаем сброс таймера по совпадению
TIMER2_COMPA_setValue(124); // настраиваем следование прерываний с частотой 1000 гц
TIMER2_attach_COMPA(); // прерывание с опросом энкодера
// Настройка дисплея и вывод привета.
disp.clear();
disp.brightness(1);
int8_t welcome_banner[] = { _empty, _empty, _dash, _dash, _r, _u, _n, _dash, _dash, _empty, _empty};
disp.runningString(welcome_banner, sizeof(welcome_banner), 200);
disp.displayInt(0);
dz.rate = 0;
dz.totalVolume = 0;
stepsCount = 0;
// Попытка прочитать установки из EEPROM
EEPROM.get(0, stepsFor100ml);
if ((stepsFor100ml < minStepsFor100ml) or (stepsFor100ml > minStepsFor100ml * 4)) // Если в EEPROM не установлено число шагов на 100 мл, то
{
stepsFor100ml = defaultStepsFor100ml; // Установим число шагов на 100 мл по умолчанию
}
stepsForOneMl = round((float)stepsFor100ml / 100);
calcOCR1A();
dz.drinkVolume = defaultDrink;
drinkBackCounter = (uint32_t)dz.drinkVolume * stepsForOneMl - 1;
if (!digitalRead(KEY)) {
dz.currentMode = TUNING;
byte troll[4] = {_t, _u, _n, _E};
disp.displayByte(troll);
backCounter0 = 0;
infoEnable = false;
enc1.isHolded();
}
else {
dz.currentMode = RUNNING;
infoEnable = true;
}
Serial.println(dz.drinkVolume); //
Serial.println(stepsFor100ml); //
Serial.println(stepsForOneMl); //
Serial.println(drinkBackCounter); //
Serial.println("--READY--");
//Serial.end();
//wdt_enable(WDTO_8S);
}
//--------------------------------------------------------------------------------------
//---------------------- Начало основного цикла ----------------------------------------
void loop()
{
if (TWAR!=TWI_SA) TWAR=TWI_SA;
if (newSecond) {
newSecond = false;
if (infoEnable)
{
calcTotalVolume();
disp.displayInt(dz.totalVolume % 10000);
}
}
//C;
if (newTenth) {
newTenth = false;
oneTenthSub();
}
if (bc0flag) {
bc0flag = false;
infoEnable = true;
}
//---------------------------------------------------------------
switch (dz.currentMode)
{
//-------------------------------------------------------------
// Режим калибровки насоса основной экран ---------------------
//-------------------------------------------------------------
case TUNING: // Настройка количества шагов на 100 мл.
{
infoEnable = false;
//--------------------
if (bc1flag)
{
bc1flag = false;
byte troll[4] = {_t, _u, _n, _E};
disp.displayByte(troll);
}
//--------------------
if (enc1.isRight()) // Поворот по часовой стрелке увеличивает частоту шагов
{
increaseRate();
stepEnabled = true;
disp.displayInt(dz.rate);
backCounter1 = 20;
}
//--------------------
if (enc1.isLeft()) // Поворот против часовой стрелки уменьшает частоту шагов
{
decreaseRate();
if (dz.rate != 0)
{
stepEnabled = true;
}
disp.displayInt(dz.rate);
backCounter1 = 20;
}
//--------------------
if (enc1.isClick())
{
stepEnabled = false;
dz.currentMode = TUNING_PAUSE;
byte troll[4] = {_t, _P, _A, _u};
disp.displayByte(troll);
}
//--------------------
if (enc1.isHolded())
{
setup();
}
//--------------------
}
break;
//-------------------------------------------------------------
// Пауза в режиме калибровки насоса ---------------------------
//-------------------------------------------------------------
case TUNING_PAUSE:
{
//--------------------
if (bc1flag)
{
bc1flag = false;
counterA = 0;
byte troll[4] = {_t, _P, _A, _u};
disp.displayByte(troll);
}
//--------------------
if (enc1.isRight()) // Поворот по часовой стрелке увеличивает частоту шагов
{
increaseRate();
disp.displayInt(dz.rate);
backCounter1 = 20;
}
//--------------------
if (enc1.isLeft()) // Поворот против часовой стрелки уменьшает частоту шагов
{
decreaseRate();
disp.displayInt(dz.rate);
backCounter1 = 20;
}
//--------------------
if (enc1.isClick())
{
stepEnabled = true;
dz.currentMode = TUNING;
byte troll[4] = {_t, _u, _n, _E};
disp.displayByte(troll);
}
//--------------------
if (enc1.isHolded())
{
stepsCount = 0;
dz.totalVolume = 0;
int8_t welcome_banner[] = {_c, _o, _u, _n, _t, _E, _r, _S, _empty, _c, _l, _E, _a, _r, _E, _d};
disp.runningString(welcome_banner, sizeof(welcome_banner), 200);
bc1flag = true;
}
//--------------------
if (enc1.isRightH())
{
tryToSaveStepsFor100ml();
}
//--------------------
if (enc1.isLeftH())
{
tryToSaveStepsFor100ml();
}
//--------------------
}
break;
//-------------------------------------------------------------
// Основной режим. Идёт отбор. --------------------------------
//-------------------------------------------------------------
case RUNNING:
{
//--------------------
if (enc1.isClick()) // Клик на кнопку (режим RUNNING)
{
stepEnabled = false;
dz.currentMode = PAUSED;
byte troll[4] = {_S, _t, _o, _P};
disp.displayByte(troll);
backCounter0 = 0;
infoEnable = false;
}
//--------------------
if (tmasStop) // Внешний сигнал, появление (режим RUNNING)
{
stepEnabled = false;
dz.currentMode = PAUSED_BY_EXT;
byte troll[4] = {_o, _u, _t, _S};
disp.displayByte(troll);
backCounter0 = 0;
infoEnable = false;
pattern = soundB;
sndFlag = true;
}
//--------------------
if (drinkStop) // Налит запрошенный объем (режим RUNNING)
{
stepEnabled = false;
drinkStop = false;
dz.currentMode = PAUSED_BY_VOL;
drinkBackCounter = (uint32_t)dz.drinkVolume * stepsForOneMl - 1;
int8_t troll[4] = {_d, _o, _n, _E};
disp.twistByte(troll, 20);
//disp.displayByte(troll);
backCounter0 = 0;
infoEnable = false;
pattern = soundA;
sndFlag = true;
}
//--------------------
if (enc1.isRight()) // Вращение по часовой (режим RUNNING)
{
if (backCounter0 != 0)
{
increaseRate();
stepEnabled = true;
}
disp.displayInt(dz.rate);
infoEnable = false;
backCounter0 = 20;
}
//--------------------
if (enc1.isLeft()) // Вращение против часовой (режим RUNNING)
{
if (backCounter0 != 0)
{
decreaseRate();
if (dz.rate != 0)
{
stepEnabled = true;
}
}
disp.displayInt(dz.rate);
infoEnable = false;
backCounter0 = 20;
}
//--------------------
if (enc1.isHolded()) // Удержание кнопки (режим RUNNING)
{
if ((dz.rate == 0) and (stepsCount != 0))
{
stepsCount = 0;
dz.totalVolume = 0;
drinkBackCounter = (uint32_t)dz.drinkVolume * stepsForOneMl - 1;
int8_t welcome_banner[] = {_c, _o, _u, _n, _t, _E, _r, _S, _empty, _c, _l, _e, _a, _r, _e, _d};
disp.runningString(welcome_banner, sizeof(welcome_banner), 200);
}
else
{
if (infoEnable) {
if (dz.drinkVolume == 0)
{
byte troll[4] = {_empty, _i, _n, _f};
disp.displayByte(troll);
}
else
{
disp.displayInt((drinkBackCounter + 1) / stepsForOneMl);
}
}
infoEnable = false;
backCounter0 = 20;
}
}
//--------------------
}
break;
//-------------------------------------------------------------
// Остановка по нажатию кнопки --------------------------------
//-------------------------------------------------------------
case PAUSED:
{
//--------------------
if (bc1flag)
{
bc1flag = false;
//stepEnabled = false;
byte troll[4] = {_S, _t, _o, _P};
disp.displayByte(troll);
infoEnable = false;
}
//--------------------
if (enc1.isClick())
{
resumeRun();
}
//--------------------
if (enc1.isRight())
{
if (backCounter1 != 0)
{
increaseRate();
}
disp.displayInt(dz.rate);
infoEnable = false;
backCounter1 = 20;
}
//--------------------
if (enc1.isLeft())
{
if (backCounter1 != 0)
{
decreaseRate();
}
disp.displayInt(dz.rate);
infoEnable = false;
backCounter1 = 20;
}
//--------------------
if (enc1.isHolded())
{
infoEnable = false;
dz.currentMode = SELECT_VOL;
byte troll[4] = {_S, _t, _E, _P};
disp.displayByte(troll);
}
//--------------------
}
break;
//-------------------------------------------------------------
// Остановка по внешнему сигналу ------------------------------
//-------------------------------------------------------------
case PAUSED_BY_EXT:
{
if (!tmasStop)
{
sndFlag = false;
//backCounter1 = 10;
resumeRun();
}
//--------------------
if (enc1.isRight() || enc1.isLeft() || enc1.isClick())
{
//backCounter1 = 250;
sndFlag = false;
}
//--------------------
/*
if ((!sndFlag) && (backCounter1 == 0))
{
sndFlag = true;
}*/
}
break;
//-------------------------------------------------------------
// Остановка по достижению заданного разового объема отбора ---
//-------------------------------------------------------------
case PAUSED_BY_VOL:
{
//--------------------
if (enc1.isHolded())
{
infoEnable = false;
dz.currentMode = SELECT_VOL;
byte troll[4] = {_S, _t, _E, _P};
disp.displayByte(troll);
sndFlag = false; // Заткнуть пищалку
}
//--------------------
if (enc1.isClick())
{
sndFlag = false; // Заткнуть пищалку
resumeRun();
}
//--------------------
if (enc1.isRight())
{
sndFlag = false; // Заткнуть пищалку
}
//--------------------
if (enc1.isLeft())
{
sndFlag = false; // Заткнуть пищалку
}
//--------------------
}
break;
//-------------------------------------------------------------
// Режим выбора разового объема -------------------------------
//-------------------------------------------------------------
case SELECT_VOL:
{
//--------------------
if (bc1flag)
{
bc1flag = false;
byte troll[4] = {_S, _t, _E, _P};
disp.displayByte(troll);
}
//--------------------
if (enc1.isHolded())
{
drinkBackCounter = (uint32_t)dz.drinkVolume * stepsForOneMl - 1;
resumeRun();
}
//--------------------
if (enc1.isClick())
{
dz.currentMode = PAUSED;
drinkBackCounter = (uint32_t)dz.drinkVolume * stepsForOneMl - 1;
byte troll[4] = {_S, _t, _o, _P};
disp.displayByte(troll);
}
//--------------------
if (enc1.isRight())
{
if (backCounter1 != 0)
{
if (dz.drinkVolume >= 1000) {
dz.drinkVolume = dz.drinkVolume + volBigStep;
} else {
if (dz.drinkVolume >= 100) {
dz.drinkVolume = dz.drinkVolume + volMidStep;
} else {
dz.drinkVolume = dz.drinkVolume + volStep;
}
}
if (dz.drinkVolume >= maxDrinkVol) dz.drinkVolume = 5000;
}
disp.displayInt(dz.drinkVolume);
backCounter1 = 20;
}
//--------------------
if (enc1.isLeft())
{
if (backCounter1 != 0)
{
if (dz.drinkVolume >= (1000 + volBigStep)) {
dz.drinkVolume = dz.drinkVolume - volBigStep;
} else {
if (dz.drinkVolume >= (100 + volMidStep)) {
dz.drinkVolume = dz.drinkVolume - volMidStep;
} else {
dz.drinkVolume = dz.drinkVolume - volStep;
}
}
if (dz.drinkVolume <= 0) dz.drinkVolume = 0;
}
disp.displayInt(dz.drinkVolume);
backCounter1 = 20;
}
//--------------------
}
break;
//-------------------------------------------------------------
default:
//-------------------------------------------------
break;
}
//wdt_reset();
//-------------------------------------------------
}
//---------------------- Конец основного цикла -----------------------------------------
//--------------------------------------------------------------------------------------
void resumeRun()
{
byte troll[4] = {_dash, _G, _o, _dash};
disp.displayByte(troll);
dz.currentMode = RUNNING;
if (dz.rate != 0)
{
stepEnabled = true;
}
backCounter0 = 5;
}
//--------------------------------------------------------------------------------------
// То, что выполняется каждую секунду --------------------------------------------------
//--------------------------------------------------------------------------------------
// То, что выполняется каждую десятую долю секунды -------------------------------------
void oneTenthSub()
{
tmasStop = !digitalRead(TMAS);
digitalWrite(13, tmasStop);
if ((sndFlag) and (tenth < 8))
{
if (bitRead(pattern, tenth))
{
digitalWrite(PIEZO, 0);
}
else
{
digitalWrite(PIEZO, 1);
}
}
else
{
digitalWrite(PIEZO, 1);
}
}
//--------------------------------------------------------------------------------------
// Прерывание таймера 2 (1000 раз в секунду) -------------------------------------------
ISR_T2_COMPA
{
enc1.tick();
thousandth++; // Счетчик миллисекунд
if (thousandth >= 100) // Началась новая десятая доля секунды
{ thousandth = 0; tenth++; newTenth = true; // Счетчик десятых долей секунды
if (backCounter0 != 0) {
backCounter0--;
if (backCounter0 == 0) {
bc0flag = true;
}
}
if (backCounter1 != 0) {
backCounter1--;
if (backCounter1 == 0) {
bc1flag = true;
}
}
if (tenth >= 10) {
tenth = 0; // Началась новая секунда
newSecond = true;
}
}
}
//--------------------------------------------------------------------------------------
// Прерывание по совпадению А в таймере 1 ----------------------------------------------
ISR_T1_COMPA
{
if ((stepEnabled) or (!(stepEnabled) and !(digitalRead(STEP).
// Если шаги разрешены или запрещены и уровень на тактовом выходе низкий, то:
{
digitalWrite(STEP, !digitalRead(STEP)); // Меняем уровень на шагательной ноге на противоположный
if (digitalRead(STEP)) // Если был переход 0->1,
{
stepsCount++; // то увеличиваем счетчик шагов
TIMER1_COMPA_setValue(timer1EndValue); // и перезагружаем значение сравнения счетчика.
if (dz.drinkVolume != 0) // Если задан ненулевой объем наливайки
{
if (drinkBackCounter == 0) // и налито, сколько запрошено,
{
stepEnabled = false; // останавливаем отбор
drinkStop = true; // и устанавливаем флаг готовности дринка. (обрабатывается в основном цикле)
}
else
{
drinkBackCounter--; // Иначе уменьшаем дринковый счетчик.
}
}
}
}
}
//--------------------------------------------------------------------------------------
// Расчет числа, загружаемого в OCR1A в зависимости от нужной скорости отбора ----------
void calcOCR1A()
{
stepEnabled = false;
temp = round((float)450000000 / stepsForOneMl); // шаг/4
#ifdef STEP8
temp = round((float)3600000000 / stepsForOneMl); // шаг/8
#endif
// OCR1A = (Fcpu*3600)/(2*N*K*R)-1
temp = round((float)temp / dz.rate); // Fcpu = 16000000 Гц, N - количество шагов на 1 мл,
temp = temp - 1; // K - делитель перед счетчиком Т1 (64), R - скорость отбора мл/час
if (temp >= 65535)
{
dz.rate = 0;
disp.displayInt(dz.rate);
}
else
{
noInterrupts(); // Обеспечиваем атомарность действия
timer1EndValue = temp; //
interrupts(); // Восстанавливаем прерывания
}
}
//--------------------------------------------------------------------------------------
// Пересчёт количества шагов в миллилитры ----------------------------------------------
void calcTotalVolume()
{
dz.totalVolume = stepsCount / stepsForOneMl;
}
//--------------------------------------------------------------------------------------
// Увеличение скорости отбора ----------------------------------------------------------
void increaseRate()
{
if (dz.rate >= 1000) {
dz.rate = dz.rate + rateBigStep;
} else {
if (dz.rate >= 200) {
dz.rate = dz.rate + rateMidStep;
} else {
dz.rate = dz.rate + rateStep;
}
}
if (dz.rate >= maximumRate) dz.rate = maximumRate;
calcOCR1A();
}
//--------------------------------------------------------------------------------------
// Уменьшение скорости отбора ----------------------------------------------------------
void decreaseRate()
{
if (dz.rate >= (1000 + rateBigStep)) {
dz.rate = dz.rate - rateBigStep;
} else {
if (dz.rate >= (200 + rateMidStep)) {
dz.rate = dz.rate - rateMidStep;
} else {
dz.rate = dz.rate - rateStep;
}
}
if (dz.rate <= 0) dz.rate = 0;
calcOCR1A();
}
//--------------------------------------------------------------------------------------
void tryToSaveStepsFor100ml()
{
backCounter1 = 20;
counterA++;
if (counterA > 10)
{
if ((stepsCount > minStepsFor100ml) and (stepsCount < 4 * minStepsFor100ml))
{
EEPROM.put(0, stepsCount);
int8_t welcome_banner[] = {_C, _A, _L, _i, _b, _r, _A, _t, _i, _n, _G, _empty, _d, _o, _n, _E, _empty, _r, _E, _S, _t, _A, _r, _t, _i, _n, _G, _empty, _empty};
disp.runningString(welcome_banner, sizeof(welcome_banner), 200);
setup();
}
}
}
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
У меня ведущее устройство esp32(код esp idf).
Если надо, набросаю код ведущего под arduino.
Небольшой комментарий про глобальные переменные используемые в обработчиках прерывания - их нужно обьявлять как volatile.
Парни подскажите что делать. ошибка компиляции для ардуино нано прошивка из 198 поста Arduino: 1.8.5 (Windows 7), Плата:"Arduino Nano, ATmega168"
C:\Program Files\Arduino\arduino-builder -dump-prefs -logger=machine -hardware C:\Program Files\Arduino\hardware -hardware C:\Users\Teminator\AppData\Local\Arduino15\packages -tools C:\Program Files\Arduino\tools-builder -tools C:\Program Files\Arduino\hardware\tools\avr -tools C:\Users\Teminator\AppData\Local\Arduino15\packages -built-in-libraries C:\Program Files\Arduino\libraries -libraries C:\Users\Teminator\Documents\Arduino\libraries -fqbn=arduino:avr:nano:cpu=atmega168 -ide-version=10805 -build-path C:\Users\TEMINA~1\AppData\Local\Temp\arduino_build_43420 -warnings=none -build-cache C:\Users\TEMINA~1\AppData\Local\Temp\arduino_cache_488511 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.arduinoOTA.path=C:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.1.1 -prefs=runtime.tools.avr-gcc.path=C:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2 -prefs=runtime.tools.avrdude.path=C:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino9 -verbose C:\Users\Teminator\Desktop\dozer\pump_v0\pump_v0.ino
C:\Program Files\Arduino\arduino-builder -compile -logger=machine -hardware C:\Program Files\Arduino\hardware -hardware C:\Users\Teminator\AppData\Local\Arduino15\packages -tools C:\Program Files\Arduino\tools-builder -tools C:\Program Files\Arduino\hardware\tools\avr -tools C:\Users\Teminator\AppData\Local\Arduino15\packages -built-in-libraries C:\Program Files\Arduino\libraries -libraries C:\Users\Teminator\Documents\Arduino\libraries -fqbn=arduino:avr:nano:cpu=atmega168 -ide-version=10805 -build-path C:\Users\TEMINA~1\AppData\Local\Temp\arduino_build_43420 -warnings=none -build-cache C:\Users\TEMINA~1\AppData\Local\Temp\arduino_cache_488511 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.arduinoOTA.path=C:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.1.1 -prefs=runtime.tools.avr-gcc.path=C:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2 -prefs=runtime.tools.avrdude.path=C:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino9 -verbose C:\Users\Teminator\Desktop\dozer\pump_v0\pump_v0.ino
Using board 'nano' from platform in folder: C:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21
Using core 'arduino' from platform in folder: C:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21
Изменены опции сборки, пересобираем все
Detecting libraries used...
"C:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -flto -w -x c++ -E -CC -mmcu=atmega168 -DF_CPU=16000000L -DARDUINO=10805 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR "-IC:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\cores\arduino" "-IC:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\variants\eightanaloginputs" "C:\Users\TEMINA~1\AppData\Local\Temp\arduino_build_43420\sketch\pump_v0.ino.cpp" -o "nul"
"C:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -flto -w -x c++ -E -CC -mmcu=atmega168 -DF_CPU=16000000L -DARDUINO=10805 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR "-IC:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\cores\arduino" "-IC:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\variants\eightanaloginputs" "-IC:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\libraries\EEPROM\src" "C:\Users\TEMINA~1\AppData\Local\Temp\arduino_build_43420\sketch\pump_v0.ino.cpp" -o "nul"
"C:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -flto -w -x c++ -E -CC -mmcu=atmega168 -DF_CPU=16000000L -DARDUINO=10805 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR "-IC:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\cores\arduino" "-IC:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\variants\eightanaloginputs" "-IC:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\libraries\EEPROM\src" "C:\Users\TEMINA~1\AppData\Local\Temp\arduino_build_43420\sketch\pump_v0.ino.cpp" -o "C:\Users\TEMINA~1\AppData\Local\Temp\arduino_build_43420\preproc\ctags_target_for_gcc_minus_e.cpp"
C:\Users\Teminator\Desktop\dozer\pump_v0\pump_v0.ino:2:85: fatal error: GyverEncoder.h: No such file or directory
#include "GyverEncoder.h" // Библиотеки с сайта
^
compilation terminated.
Несколько библиотек найдено для "EEPROM.h"
Используется: C:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\libraries\EEPROM
Не используется: C:\Users\Teminator\Documents\Arduino\libraries\EEPROM
Используем библиотеку EEPROM версии 2.0 из папки: C:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\libraries\EEPROM
exit status 1
Ошибка компиляции для платы Arduino Nano.
все разобрался библиотеки не добавил
Доброго времени суток , собрал и запустил пересталический насос, подскажите у всех шаговик жутко греется, и как исправить?, и почему при нажатии на остановку моторчик свистит, ведь по идее с него должно сниматься все напряжение?
шаговик жутко греется, и как исправить?,
Жутко греется, если сильно завышен ток обмоток двигателя относительно номинального.
Исправляется вращением подстроечника на плате с DRV8825.
Где-то в предыдущих постах было как это сделать с приведением числовых значений.
Вот тут:
Узел отбора на перистальтическом насосе
примерно посередине поста.
---
С этим же связано:
и почему при нажатии на остановку моторчик свистит,
При остановке ток с обмоток не снимается.
Микросхема драйвера старается поддерживать средний ток через обмотки на заданной подстроечником величине.
Делает она это импульсным способом.
А так как установленный ток слишком велик, то железо моторчика может начать свистеть.
По типу гудения трансформатора, только частотой выше.
Жутко греется, если сильно завышен ток обмоток двигателя относительно номинального.
Исправляется вращением подстроечника на плате с DRV8825.
Где-то в предыдущих постах было как это сделать с приведением числовых значений.
Вот тут:
Узел отбора на перистальтическом насосе
примерно посередине поста.
---
С этим же связано:При остановке ток с обмоток не снимается.
Микросхема драйвера старается поддерживать средний ток через обмотки на заданной подстроечником величине.
Делает она это импульсным способом.
А так как установленный ток слишком велик, то железо моторчика может начать свистеть.
По типу гудения трансформатора, только частотой выше.
Я всяко крутил, и как нащел момент чтоб мотрчик начинал крутиться с самого начала, но тогда он встовал при высоких оборотах и на экране вылазили какая-то ошибка вроде ---run, после чего не реагировала на энкодер, как нашел то положение при котором работает во всех режимах оставил поработать в итоге немного поработав сдохла ардуинка, экран и драйвер , похоже не тянет она 12в
Dimyn999, похоже блок питания чудит.
У меня совершенно спокойно от 24 вольт работает.
Правда на питание ардуины отдельно понижаю до 9 вольт.
Правда на питание ардуины отдельно понижаю до 9 вольт.
я от 12в блок питания от старого модема, похоже все таки придется ставить отдельный стабилизатор
12в блок питания от старого модема
Не слабоват? Движок может ампер легко слопать. А то и больше.
Возьми от ноутбука БП.
Не слабоват? Движок может ампер легко слопать. А то и больше.
Возьми от ноутбука БП.
у меня шаговик не такой большой и мощный, от принтера, есть бп на 14в на 5А, но боюсь от него мотор сдохнет
есть бп на 14в на 5А, но боюсь от него мотор сдохнет
Не сдохнет, ставь.
Драйвер не даст.
Драйвер не даст.
а он не сдохнет?
а он не сдохнет?
Не должен.
Он по напряжению 45 вольт должен держать, а при 24 вольтах - 2,5 ампера по току на выход.
Кстати, у него минимум 8,2 вольта по питанию.
Так что низкое напряжение ему не очень хорошо.
На финальном испытании понял, что мне надо бы поменять направление вращения двигателя.
kvic, я так понимаю, что программно в скетче этого сделать нельзя?
программно в скетче этого сделать нельз
Нельзя, вывод направления не используется.
Поменяй местами выводы одной из обмоток двигателя.
kvic,
с 261 по 280 из 1 059