Запоминание позиий серво

vvadim
Онлайн
Зарегистрирован: 23.05.2012

В программировании чайник, но стало интересно возиться с ардуиной. Возникла проблемка.

Есть серва, положение которой определяется потенциометром. С помощью кнопки заношу в память положение сервы- перевожу потенциометром в другое положение -нажимаю кнопку загрузки памяти. Серва поворачивается в сохранённое положение и сразу возвращается в положение, определяемое потенциометром на данный момент. Как отключить чтение данных с аналогово входа или есть другие решения? Надеюсь на помощ специалистов.

 

maksim
Offline
Зарегистрирован: 12.02.2012

После нажатия на кнопку загрузки из памяти серва остается в сохраненном положении пока значение на аналоговом входе не изменится.

Код свой выложите. Вставка программного кода в тему/комментарий

vvadim
Онлайн
Зарегистрирован: 23.05.2012
void loop(){
  
  // привожу серву в положение А
  val = analogRead(potpin);        
  val = map(val, 0, 1023, 0, 179); 
  myservo.write(val); 
  delay(15); 
  
  //кнопкой 1 записываю в память положение А  
  if(button1State == HIGH) {      
     EEPROM.write(addr, val / 4);  //     
     addr = addr + 1;
     if (addr == 512)
     addr = 0;  
     delay(100); 
    
   //потенциометром перевожу серву в положение В

   //кнопкой 2 перевожу серву в положение А
   if(button2State == HIGH) {       
      value = EEPROM.read(addr);          
      addr = addr + 1;
      if (addr == 512)
      addr = 0;    
      delay(100);
    
      myservo.write(value * 4);
      delay(1000);
      
   //сейчас серва переходит в А и сразу возвращается в В
   
   // кнопкой 3 возвращаю серву в полпжение В
  ???????????????????             
                                        
   // продолжаю потенциометром вращать серву
  ???????????????????             
                                        
   //кнопкой 4 очищаю память
   if(button4State == HIGH) {         
        EEPROM.write(addr, 0);
                                                         
                                                         
      

 

leshak
Offline
Зарегистрирован: 29.09.2011

Вы сами практически ответили на свой вопрос.

"отключить чтение данных с аналогово входа"

 Вам нужно завести еще одну какую-то переменную (глобальную, объявленную вне loop), например inputMode, в которой вы будете хранить нужно сейчас читать состояние потенциометра или нет.

обернуть строчки которые вам нужно "отключить" (04-07) в 

if(inputMode){ .... читаем потенциометр }

На у дальше, там где вы работаете с нопками, выставляете inputMode=0, если вам нужно игнорить потенциометр, и inputMode=1,  если нужно следить за ним.

 

Не знаю толком вашей задачи, но, возможно, тут, с точки зрения пользователя, будет более удобней использовать не потенциометр, а энкодер. Типа "кнопкой" из памяти "грубо" установили позицию сервы, потом энкодером "уточнили" и опять кнопой "запомнили" новую позицию.

Хотя с энкодера, конечно, читать данные несколько сложней чем с потенциометра. Зато у него нет такого понятия как "собственная позиция". Он может говорить только "меня повернули на 15 градусов по часовой, или 30 градусов против-часовой", и крутится он без ограничителей.

vvadim
Онлайн
Зарегистрирован: 23.05.2012
int inputMode();

void loop(){
  
  if(inputMode) {
  val3 = analogRead(potpin);           
  ....................
  }  
    
 
  if(button2State == HIGH) {    
  value = EEPROM.read(addr);  
  
  inputMode==0;
  
  myservo.write(value * 4);
  delay(1000);
  }
  if(button4State == HIGH) {
  inputMode==1; 
   
  } 
}
 //без кнопки 4 компилируется
//с кнопкой 4 пишет ошибку
//ISO C++forbids comparison between
//pointer and integer
//не могу разобраться
Что я делаю не правильно?

 

leshak
Offline
Зарегистрирован: 29.09.2011

 >Что я делаю не правильно?

Предполагаете наличие телепатов на форуме.

Вы что Ленин в революционные годы, что-бы бумагу экономить? Почему не дать скетч целиком?

Да и форумную переписку зачем комментариями делать? Почему описание ситуации нельзя просто после/до скетча написать?

Да и переменную inputMode вы как-то загадисто объявили. Посмотретие в справочнике (в шапке сайта , ссылка "Программирование"), как переменные объявляются.

vvadim
Онлайн
Зарегистрирован: 23.05.2012

#include  <Servo.h>
#include <EEPROM.h>

Servo myservo;

int button1Pin = 4;              
int button2Pin = 2;
int button3Pin = 6;
int button4Pin = 7;

int inputMode;
                       
int button1State;               
int button2State;
int button3State;
int button4State;
int potpin = 0;
int val3;
int val4 = analogRead(0) / 4;
int addr = 0;
byte value;


void setup() {
  pinMode(button1Pin, INPUT);    
  pinMode(button2Pin, INPUT);
  pinMode(button3Pin, INPUT);
  pinMode(button4Pin, INPUT);  
  myservo.attach(9);
  button1State = digitalRead(button1Pin);  
  button2State = digitalRead(button2Pin);
  button3State = digitalRead(button3Pin);
  button4State = digitalRead(button4Pin);
}

void loop(){
  
  if(inputMode) {
  val3 = analogRead(potpin);           
  val3 = map(val3, 0, 1023, 0, 179);   
  myservo.write(val3);                 
  delay(15);
  } 
  
   
  
  if(button1State == HIGH) {
        
  EEPROM.write(addr, val4);
  addr = addr + 1;
  if (addr == 512)
  addr = 0;  
  delay(100);
  }  
                   
     
  if(button2State == HIGH) {    
  value = EEPROM.read(addr);
  addr = addr + 1;                                                          
                                                          
  if (addr == 512)
  addr = 0;    
  delay(100);     
  inputMode==0;
  myservo.write(value * 4);
  delay(1000);
  }
 
  if(button3State == HIGH) {
    
  EEPROM.write(addr, 0);
 }
   
  if(button4State == HIGH) {
  inputMode==1; 
   
  } 
}

 

maksim
Offline
Зарегистрирован: 12.02.2012

Судя по скейтчу у вас кнопки только при включении работают. 

maksim
Offline
Зарегистрирован: 12.02.2012

И зачем остальные кнопки? 

leshak
Offline
Зарегистрирован: 29.09.2011

 Ну теперь осталось только кнопки читать не один раз, при старте скетча, а в каждом Loop.

Перенести строчки 30-33 в начало loop (вставить в 37-седьмую).

Ну и в строках 64,75 не сравнивать inputMode с нулем и единицей, а менять его значение. Посмотрите как я написал "выставляете ... если вам нужно". И как вы сделали. Найдите отличие (всего один символ ;)

Так же, возможно, при инициализации inputMode, наверное стоит ему указать начальное значение 1, что-бы при старте скетча сразу начинал работать потенциометр (так как сейчас - потенциометр заработает только после нажатия четвертной кнопки.)

vvadim
Онлайн
Зарегистрирован: 23.05.2012

 кнопка 1-запись положения в память

кнопка 2-загрузка данных из памяти и перевод сервы в сохранённое положение

кнопка 3-очистка памяти

кнопка 4-включение чтения данных с потенциометра и перевод сервы из сохранённого положения в положение определяемое потенциометром

vvadim
Онлайн
Зарегистрирован: 23.05.2012

leshak,  Спасибо за помощ. Сделал как вы посоветовали - заработало. Правда серва всё время уходит в крайнее положение. Или что-то с записью в память или очисткой памяти. Попробую покопаться может получиться. Ну и дребезг кнопок вставить в скетч.

leshak
Offline
Зарегистрирован: 29.09.2011

 > Или что-то с записью в память или очисткой памяти.

Конечно....

Вы же читаете в потенциометр в val3, а в память сохраняете val4, которую установили один раз. при инициализации скетча. Причем, извините, способом из серии  "почесать правое ухо левой ногой". 

vvadim
Онлайн
Зарегистрирован: 23.05.2012

 Я первый раз в программировании. 

Попробовал вычисление val4 перенести в loop    для кнопки 1 -то же самое. Застрял. А ещё надо добиться плавного перевода сервы из одного положения в другое...

leshak
Offline
Зарегистрирован: 29.09.2011

> Я первый раз в программировании.

Ну и что? Я же не над вами, как личностью, иронизировал, а над способом чтения. Первый раз вижу digitalRead в инициализации переменных.

А "сам себе злобный буратино", так это постоянно бывают и те кто сто тысячный раз в программировании. Причем все :)

Сам процесс програмления, это постоянный цикл "плавных приближений". Итерации "накидал, выяснил почему не работает, поправил". Так что нечего смущатся. Это совершенно естественный процесс написания кода. "Сразу с листа правильно" пишутся только очень примитивные вещи, в несколько строк, и то не всегда :)

А вот навыки выяснения "почему не работает как хотел" - это нужно развивать. Без этого - никак.

 >Попробовал вычисление val4 перенести в loop для кнопки 1 -то же самое. Застрял

Ага. Как пробовал и почему застрял опять нужно телепатить?  "val4=analogRead(potpin) / 4" в 48-мую строку, не?

Нужно привыкнуть все время представлять себе контроллером, который должен выполнить этот скетч. Представте себе что переменные и память это листики вашего блокнота (именованные), что это вам нужно вписывать в них значения, сравнивать, крутить серву исходя из записей. Тогда легче будет отлавливать ситуации типа "нужно повернуть серву в соотсвесвие с записями на странице 'val4', а там ничего не записанно :(  "

Натыкайте, в критических точках, всякие Serial.print("val3:");Serial.println(val3); и смотрите в serial мониторе, чему там равны ваши переменные, смотрите насколько соотсвествует их содержимое вашим предположениям. Поизучайте работу своего скетча.

> А ещё надо добиться плавного перевода сервы из одного положения в другое

А в чем проявляется "неплавность" - снова догадайся. Слишком быстро поворачивается? Нет промежуточных значений? Неплавность при кручении реостата или при чтении-записи из памяти?

Кстати в чем магических смысл делать чтение/запись каждый раз по новому аддресу? Ну то есть "зачем" - догадатся-то можно... экономия циклов перезаписи :), только вот толку? При перезагрузке контроллера, вы же не знаете по какому адресу была последняя запись, первое чтение всегда произойдет по адресу - 0.

Я бы, наверное делал так (хотя IMHO это тоже коряво, но ничего красивше сходу не приходит в голову): 

  • При очистке, забивал нулями не одну ячейку, а все 512 (и по нажатию, кнопки и при "сбросе" счетчика при addr==512)
  • При старте скетча, устанавливал addr в 512, пытался читать, если там ноль - уменьшаем addr на единицу и опять читаем. и так до тех пор, пока не найдем ненулевое значение. Это и будет наша "текущая рабочая ячейка".

 

leshak
Offline
Зарегистрирован: 29.09.2011

 да и еще. при очистеке, перед тем как писать 0 в ячейку, можно делать чтение из нее. Если там уже 0, но незачем лишний раз делать write, нужно поберечь ресурс памяти.

vvadim
Онлайн
Зарегистрирован: 23.05.2012

 Через serial монитор видно, что загружается вроде как и ожидалось. А вот с чтением ерунда какая то. Попробую разобраться.    

По моторам- реостат работает хорошо. Тут проблем нет.  Нужно понять как регулировать скорость перехода сервы в положение из памяти и обратно. Здесь движение без потенциометра. Пробовал через delay - не получается

leshak
Offline
Зарегистрирован: 29.09.2011

 Я бы делал так:

  1. Выкинул нафиг val4, писал в память именно val3. В том виде какое оно получается после применения функции map, тогда при чтении с ним тоже ничего мудрить не нужно. Достал и, как есть, отправил на серву.
  2. Скорость сервы делал бы так: завел переменную в которую запоминаю "где сейчас серва". Когда нужно повернуть в новую позицию - вычисляем разницу между нужным положением, и текущим. И поворачиваем "по чуть-чуть", с паузами. Например сечас она на 20-ти, а нужно 50. Значит даем командау 25, пауза, 30, пауза, 35, пауза, 40, пауза, 45, пауза, 50. При достаточно малом шаге и небольших паузах - будет эффект плановсти движение. Неторопливого.
vvadim
Онлайн
Зарегистрирован: 23.05.2012

leshak пишет:

 Я бы делал так:

  1.  
  2. Скорость сервы делал бы так: завел переменную в которую запоминаю "где сейчас серва". Когда нужно повернуть в новую позицию - вычисляем разницу между нужным положением, и текущим. И поворачиваем "по чуть-чуть", с паузами. Например сечас она на 20-ти, а нужно 50. Значит даем командау 25, пауза, 30, пауза, 35, пауза, 40, пауза, 45, пауза, 50. При достаточно малом шаге и небольших паузах - будет эффект плановсти движение. Неторопливого.

Мне просто неудобно просить за меня делать программу, но , как я уже писал, это моя первая проба в программировании. я просто не знаю где об этом можно почитать и посмотреть примеры. если можно то ссылку  сбросьте. как такой метод вообще то правильно называется 

leshak
Offline
Зарегистрирован: 29.09.2011

 Никак этот метод не называется :) Название "придумал что хочу, и записал это програмными конструкциями".

Что вам важнее, "получить результат" или "самому дойти" (обучение)?

В зависимости от этого, я могу либо дать пример кода, либо "наводящими заданиями" вытягиваеть его из вас :)

Первое мне, конечно проще, второе IMHO полезней (и вам приятней, в финале. сам разобрался и написал).

Если учится, то для начала нужно прочитать http://arduino.ru/Reference/For и http://arduino.ru/Reference/While

P.S. По хорошему вообще нужно прочитать все из раздела http://arduino.ru/Reference . Хотя-бы бегло. Что-бы хоть примерно представлять из каких "програмнных кубиков" можно собирать свои скетчи. Пусть не все будет понятно с первого захода, но что-то в памяти отложится. И когда понадобится всплывет "где-то я это читал". И уж тогда внимательно, еще раз, прочитывается кусок который потребовался.

vvadim
Онлайн
Зарегистрирован: 23.05.2012

leshak пишет:

 

 

Первое мне, конечно проще, второе IMHO полезней (и вам приятней, в финале. сам разобрался и написал).

 

конечно если дадут конкретный пример или полное решение проблемы это хорошо и спасибо, но немного хочется и пониматьчто делается и зачем. учусь по немногу

leshak
Offline
Зарегистрирован: 29.09.2011

 Не ну вы все-таки решите, что вам нужней. Сразу отгадка или "горячо/холоднее"? одновременно это невозможно. Оно же взаимоисключает друг-друга ;)

vvadim
Онлайн
Зарегистрирован: 23.05.2012

ПЕРВОЕ! а теорией позанимаюсь потом. 

leshak
Offline
Зарегистрирован: 29.09.2011

 Вообщем примерно так:

#define SERVO_STEP 5 // шаг сервы в градусах, на сколько поворачиваем "за один раз"
#define STEP_DELAY 200 // пауза между шагами в миллисекундах
 

int cPos=0;// текущие положение сервы

void setServo(int newPosition){
   myservo.write(newPosition); // выкрутили серву 
   cPos=newPosition; // запомнили положение сервы
}

void setServoSlow(int newPosition){
  if(newPosition==cPos)return ;// серва уже стоит в правильно положении, ничего не делаем
  
  if(newPosition>cPos){ // если нужно повернуть на больший градус
    for(int i=cPos;i<newPosition;i+=SERVO_STEP) {
      myservo.write(i);// шагнули
      delay(STEP_DELAY);// пауза
    }
  }  else { //если нужно на меньший угол повернуть, то же самое, только по чуть-чуть уменьшаем угол
    for(int i=cPos;i>newPosition;i-=SERVO_STEP){
        myservo.write(i);// шагнули
        delay(STEP_DELAY);// пауза
    }
  }
  
  setServo(newPosition);// запомнили новое положение и довернули, если шаг был не кратен разнице позиций
}

И везде в скетче, вместо myServo.write, дальше используем setServo(...) если нужно быстро установить значение сервы и setServoSlow() если медленно.

SERVO_STEP, и STEP_DELAY - подбираем на глаз. Что-бы была медленность, но не было видимой "дергнанности"

vvadim
Онлайн
Зарегистрирован: 23.05.2012

А работа сервы с реостатом остаётся как была или тоже надо изменять код 

leshak
Offline
Зарегистрирован: 29.09.2011

 Я жне написал "везде в скетче". Значит там где реостат, myServo.write меняем на setServo()

vvadim
Онлайн
Зарегистрирован: 23.05.2012

 С очисткой памяти и загрузкой из памяти позиции сервы вроде решил проблему- указал один addres=0 и всё заработало. так можно оставить? До того как было в строчках  57-62 (брал пример из библиотеки EEPROM)  при загрузке данных из памяти выдавал 0.

leshak
Offline
Зарегистрирован: 29.09.2011

>До того как было в строчках 57-62

Наверное имелось ввиду 59-62.... иначе бред выходит.

 Ну откуда я знаю можно или нет.... это же ваш скетч :) 

Ну, предположим, я скажу "нельзя"... что дальше делать будете? А вас есть выбор "послушатся меня и иметь не работающий скетч" и проигнорировать меня (зачем тогда спрашивали?) и получить работающий (в чем вы сами убедились).

> указал один addres=0

Так будет изнашиватся одна ячейка памяти, а раньше износ распределялся на много ячеек. Сами решайте как вам лучше - убивать одну ячейку, или "много ячеек но медленее".

 

vvadim
Онлайн
Зарегистрирован: 23.05.2012

    leshak, спасибо за помощ! Работает! Теперь наверно самый трудный этап-доработать серву и завести обратную связь - точность возврата в сохранённое положение и потом обратно очень низкая.                                                                                                               И ещё вопрос - при пустой памяти и включении кнопки загрузки из памяти серва естественно переходит в 0. Нужна защита от " дурака " - при нажатии кнопки очистки памяти кнопка загрузки отключается, при нажатии кнопки сохранения в память - включается. Пробовал через  глобальную переменную типа     inputbutton2Mode     не получается . Как ещё можно?    

maksim
Offline
Зарегистрирован: 12.02.2012

Зделайте проще - проверку того что у вас записано в памяти, если 0 то при нажатии на "Загрузить" ничего не происходит.

vvadim
Онлайн
Зарегистрирован: 23.05.2012

Но  может и 0 быть записан в память-это крайнее положение сервы. Думаю правильнее кнопку блокировать. 

maksim
Offline
Зарегистрирован: 12.02.2012

Что-то я не пойму, тогда в какой момент может быть 0 если 0 означает, что ячейка стерта, ну не суть... Если вы записываете в ЕЕПРОМ, то значит питание будет отключаться, а значит использование глобальной переменной бессмысленно. Вам нужно, что бы при нажатии на "сохранить" в ЕЕПРОМ по какому нибудь адресу записывалось EEPROM.write(25, 1), а при нажатии нажатии "стереть" записывалось  EEPROM.write(25, 0) и при нажатии на "загрузить" происходила проверка:

if(EEPROM.read(25) == 1){
//то поворачиваем серву
}

 

vvadim
Онлайн
Зарегистрирован: 23.05.2012
при пустой памяти и включении кнопки загрузки из памяти серва естественно переходит в 0. Нужна защита от " дурака " - при нажатии кнопки очистки памяти кнопка загрузки отключается, при нажатии кнопки сохранения в память - включается.

 Когда при пустой памяти случайно нажать кнопку загрузки положения сервы , то серва переходит в крайнее положение соответствующее 0. Это недопустимо. 

maksim
Offline
Зарегистрирован: 12.02.2012

Так а когда положение 0 допустимо? 

vvadim
Онлайн
Зарегистрирован: 23.05.2012

Положение 0 будет тогда, когда в этом положении будет сохранение. А так получается, что допустм положение потенциометра 60 град, положение save 100 градусов , стёр память и случайно нажал загрузку из памяти и серва перешла в положение 0. 

maksim
Offline
Зарегистрирован: 12.02.2012

Понятно, я вам выше написал как это сделать, есть результаты? 

vvadim
Онлайн
Зарегистрирован: 23.05.2012
maksim, не могу понять, как блокировку кнопки запустить через память

 

maksim
Offline
Зарегистрирован: 12.02.2012

Выложите весь код, полностью!

vvadim
Онлайн
Зарегистрирован: 23.05.2012

#include  <Servo.h>
#include <EEPROM.h>
Servo myservo;
int button1Pin = 2;             
int button2Pin = 4;
int button3Pin = 6;
int button4Pin = 7;
int inputMode = 1;
int val;                        
int val2;                       
int button1State;               
int button2State;
int button3State;
int button4State;
int potpin = 0;
int val3;

int addr = 0;
void setup() {
  pinMode(button1Pin, INPUT);    
  pinMode(button2Pin, INPUT);
  pinMode(button3Pin, INPUT);
  pinMode(button4Pin, INPUT);
  
  myservo.attach(9);
}

void loop(){
  button1State = digitalRead(button1Pin);   
  button2State = digitalRead(button2Pin);
  button3State = digitalRead(button3Pin);
  button4State = digitalRead(button4Pin);
  
  if(inputMode) {
  val3 = analogRead(potpin);           
  val3 = map(val3, 0, 1023, 0, 179);   
  myservo.write(val3);                 
  delay(15);
  } 
  
  if(button1State == HIGH) {           // button 1 save        
  EEPROM.write(addr, val3);
  delay(100); 
  } 
  
  if(button2State == HIGH) {             // button 2  load
    
  value = EEPROM.read(addr);                                                 
 
  delay(100); 
   
    
    inputMode=0;
    
    myservo.write(value);
    delay(100);
  }  
  
  if(button3State == HIGH) {             // button 3 clear
 
  EEPROM.write(addr, 0);  
 
 }
 

  if(button4State == HIGH) {                // button 4 motion  
    
  inputMode=1;
   
  }
  
}

 

maksim
Offline
Зарегистрирован: 12.02.2012
#include  <Servo.h>
#include <EEPROM.h>
Servo myservo;
int button1Pin = 2;             
int button2Pin = 4;
int button3Pin = 6;
int button4Pin = 7;
int inputMode = 1;
int val;                        
int val2;                       
int button1State;               
int button2State;
int button3State;
int button4State;
int potpin = 0;
int val3;

int addr = 0;
void setup() {
  pinMode(button1Pin, INPUT);    
  pinMode(button2Pin, INPUT);
  pinMode(button3Pin, INPUT);
  pinMode(button4Pin, INPUT);

  myservo.attach(9);
}

void loop(){
  button1State = digitalRead(button1Pin);   
  button2State = digitalRead(button2Pin);
  button3State = digitalRead(button3Pin);
  button4State = digitalRead(button4Pin);

  if(inputMode) {
    val3 = analogRead(potpin);           
    val3 = map(val3, 0, 1023, 0, 179);   
    myservo.write(val3);                 
    delay(15);
  } 

  if(button1State == HIGH) {           // button 1 save   
    EEPROM.write(addr, val3);
    EEPROM.write(25, 1);  
    delay(100); 
  } 

  if(button2State == HIGH && EEPROM.read(25) == 1) { // button 2  load    
    value = EEPROM.read(addr);                                                  
    delay(100);     
    inputMode=0;    
    myservo.write(value);
    delay(100);
  }  

  if(button3State == HIGH) {             // button 3 clear 
    EEPROM.write(addr, 0); 
    EEPROM.write(25, 0);  
  }

  if(button4State == HIGH) {                // button 4 motion      
    inputMode=1;   
  }
}

  Я там опечатку нашел, так что перекопируйте еще раз.

maksim
Offline
Зарегистрирован: 12.02.2012

И если интересно, то ваш код можно вот так немного оптимизировать:

 

#include  <Servo.h>
#include <EEPROM.h>

#define button1Pin 2             
#define button2Pin 4
#define button3Pin 6
#define button4Pin 7
#define potpin 0
#define servopin 9

Servo myservo;

boolean inputMode = 1;
int val = 0;                        

void setup() {
  myservo.attach(servopin);
}

void loop(){

  if(inputMode) {          
    val = map(analogRead(potpin), 0, 1023, 0, 179);   
    myservo.write(val);                 
    delay(15);
  } 

  if(digitalRead(button1Pin)) {           // button 1 save   
    EEPROM.write(0, val);
    EEPROM.write(25, 1);  
    delay(100); 
  } 

  if(digitalRead(button2Pin) && EEPROM.read(25)) { // button 2  load    
    val = EEPROM.read(0);           
    myservo.write(val);
    inputMode=0;
    delay(100);
  }  

  if(digitalRead(button3Pin)) {             // button 3 clear 
    EEPROM.write(0, 0); 
    EEPROM.write(25, 0);  
    delay(100);
  }

  if(digitalRead(button4Pin)) {                // button 4 motion      
    inputMode=1;  
    delay(100); 
  }
}

 

vvadim
Онлайн
Зарегистрирован: 23.05.2012

 Вот теперь кнопка отключилась. Спасибо maksim. Буду осваивать обратную связь сервы и ардуино.                                                                                                                           Есть вопрос.  Насколько критично использование одной ячейки памяти. В описании написано, что допустимо 100000 перезаписей. Я просто немного задолбался уже-так код работает, а со всеми ячейками нет. Надо переделывать, а нехочется

maksim
Offline
Зарегистрирован: 12.02.2012

Если на кнопку "сохранить" нажамать 50 раз в день, то одна ячейка прослужит около 5 лет.

leshak
Offline
Зарегистрирован: 29.09.2011

 А зачем две ячейки заюзывать? Не проще-ли, пожертвовать одним градусом (фиг его на глаз заметишь), и делать маппинг не 0-179, а 0-178.

Ну и сохранять, не EPROM.write(0,val+1);, а читать val = EEPROM.read(0)+1; , очищать EPROM.write(0,0), проверять есть-ли что-то в ячейка if(EPROM.read(0))

>Надо переделывать, а нехочется

Если цель - учеба, то нужно переделывать. Тем более что там переделывать - нефиг плюнуть

Очистку делать примерно так:

for(int i=0;i<512;i++)EPROM.write(i,0);

Запись так

EPROM.write(addr,val+1);
addr++;
if(addr>=512)addr=0;

Ну и в setup, находить текущий адресс (последняя ячейка больше нуля)


for(addr=511;addr>=0;addr--){
  if(EPROM.read(addr))break;
}

 

maksim
Offline
Зарегистрирован: 12.02.2012

Можно тогда не градусом жертвовать, а просто при нажатии на "стереть" записывать в ячейку не 0, а например число 200 и проверять это при нажатии на "загрузить"

leshak
Offline
Зарегистрирован: 29.09.2011

 

maksim пишет:

Можно тогда не градусом жертвовать, а просто при нажатии на "стереть" записывать в ячейку не 0, а например число 200 и проверять это при нажатии на "загрузить"

А таки да...

Чуть-чуть проверки тогда будут многословней. Еще равно и 200-ти дописывать нужно :)

И наверное еще, стоит завести такую функию:

void eWrite(int address, byte newValue){
  if(EProm.read(address)!=newValue)EPROM.write(address,newValue);
 }

И везде использовать ее вместо EPROM.write. Тоже ресурс ячеек будет экономить. Производить запись только если новое значение отличается от содержимого ячейки.

vvadim
Онлайн
Зарегистрирован: 23.05.2012

 Всё работает, СПАСИБО за помощь! Но есть необычное явление. При движении в запомненную позицию серва в конце движения не доходя 1...2 градуса останавливается на долю секунды и доворачивает. А при обратном ходе делает движение на 1...2 град в другую сторону, а затем поворачивает в исходную позицию. При регулировании положения потенциометром этого нет. Не пойму, это проблемы самой сервы или программные вопросы.

vvadim
Онлайн
Зарегистрирован: 23.05.2012

 Добавил светодиоды и кнопки - теперь не хватает цифровых пинов. Завёл кнопки через аналоговый вход, но что то с памятью не так. При нажатии кнопки перевода в запомненную позицию просто зависает. Как при таком чтении кнопок правильнее стирать, записывать и загружать eeprom ?

 switch(buttonState){
     case BUTTON1:               //очистка памяти      
     
     EEPROM.write(addr, 0);
     EEPROM.write(25, 0);
     break;
     
     case BUTTON2:                //запись в память                                    
     
     EEPROM.write(addr, val);
     EEPROM.write(25, 1); 
     delay(100);         
     break;     
     
     case BUTTON3:                 //перевод в запомненную позицию                              
     
     inputMode1=0;
     
     EEPROM.read(25) == 1;
     value = EEPROM.read(addr);
     delay(100);
     for(pos = val; pos < value; pos += 1)                           
  {                                                                   
     myservo1.write(pos);                                              
     delay(30);                                                         
  } 
     for(pos = val1; pos > value; pos-=1)                             
  {                                
     myservo1.write(pos);                                               
     delay(30);       
     break;
     

 

maksim
Offline
Зарегистрирован: 12.02.2012

Аналоговые входы могут работать как цифровые входы/выходы....  

например на вход: 

#define button1Pin A0             
.........

void loop(){
  if(digitalRead(button1Pin)) {  
.........

или на выход:

#define LED A0
........

void setup() {
  pinMode(LED, OUTPUT);    
........

void loop(){
  digitalWrite(LED, 1);  
........

 

vvadim
Онлайн
Зарегистрирован: 23.05.2012

 У меня все цифровые выходы заняты светодиодами и сервами. Пришлось 10 кнопок заводить через аналоговый вход. Светодиодами управляет нормально. Но с памятью проблема, которой не было, когда кнопки были на цифровых пинах. Как правильно записать работу с памятью нескольких кнопок с одного аналогового входа?

maksim
Offline
Зарегистрирован: 12.02.2012

Весь код покажите