удаленная перезагрузка с помощью Arduino

lenon
Offline
Зарегистрирован: 16.01.2014

Парни подскажите такая задача.стоит 10 компов из них 1 головной .есть удаленный доступ к головному компьютеру..Задача:с помощью головного компа с подключенным к нему платой ардуино уно производить перезагрузку компьютеров.нужно маленькая програмулина для компа с цифрами  от одного до 10 или можно и просто командами.я думаю просто приделать реле к выходам чтобы они уже замыкались на секунду и комп уйдет в ребут.но  скетч написать не могу.подскажите мож кто такое делал.буду благодарен если нужно могу и деньгами отблагодорить=)если что почта lenon.f@yandex.ru или тут

Artur1985
Offline
Зарегистрирован: 19.02.2013

Cам такое не делал.

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

Вариантов может быть несколько. Да всех наверно не перечислю, так на вскидку.
Вариант 1.
Uno + Ethernet + нужное кол-во реле + вывести с каждого компа линии reset, power (если надо).
На ардуино подымается веб-сервер, он в сети, там просто кнопки около номера компа.

Вы сможете перезапускать все 11. И данное решение не зависит от работы головного ком.
Но и посложнее, особенно если надо будет авторизация (не знаком).

Вариант 2.
К первому ком. соединена ардуина по USB  + нужное кол-во реле + вывести с каждого компа линии reset, power (если надо). С помощью встроенного монитора порта отправляются команды 0-9.

Минус на мой взгляд, а вдруг головной упадет.
Но просто.

UPD. Да и ознакомьтесь с данной темой
http://arduino.ru/forum/apparatnye-voprosy/kak-vklyuchit-pk-s-pomoshchyu-arduino

lenon
Offline
Зарегистрирован: 16.01.2014

я все могу сделать по эллектронной части а вот програмную часть не знаю....мне нужна помощь тока в том как ардунио заставить включать определенный контакт а именно появление 5v на контакт на секунду и все. и чтобы это можно было сделать с компа.грубо говоря нажал на кнопочку в програме включился один из контактов.  вот подобное но как это реализовать в плане программы и управление ардунио  .пример: https://www.youtube.com/watch?v=XAWNGVBsmN4   .это идеально для меня

leshak
Offline
Зарегистрирован: 29.09.2011
#define OUT_PIN 13 // на каком пине будем HIGH генерить
#define PULSE_TIME 1000 // сколько времени будет high генерить, в миллисекундах


void setup(){
  Serial.begin(9600);
  pinMode(OUT_PIN,OUTPUT);
  printReady();
}

void printReady(){
  Serial.println("Ready");
  Serial.print("Send 'r' to raise RESET on ");
  Serial.print(OUT_PIN,DEC);
  Serial.println(" pin");
  
}

void loop(){
  
  if(Serial.available()){
      if(Serial.read()=='r'){
         raiseReset();
      }
      clearSerialInput();// очистили входящий буфер. вдруг еще что-то "затеслось", кроме команды
  }
}


void clearSerialInput(){
  while(Serial.available())Serial.read();
}

void raiseReset(){
   Serial.print("RESET....");
   
   digitalWrite(OUT_PIN,HIGH); // дали 5-ть вольт на пин
   delay(PULSE_TIME);// подождали
   digitalWrite(OUT_PIN,LOW);  // выключили

   Serial.println("DONE");
}

 

lenon
Offline
Зарегистрирован: 16.01.2014

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

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

Запускаете ArduinoIDE. Открываете Serial монитор. В строке сверху набираете буквочку 'r' и нажимате кнопку Send.

lenon
Offline
Зарегистрирован: 16.01.2014

спасибо большое.как все соберу отпишусь и раскажу как все прошло

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

Что-бы протестить, не обязательно собирать. В скетче выше для выхода используется D13. Его "особость" состоит в том, что к нему привешен светодиод. Поэтому наличие на этом пине 5v видно визуально. Без какой-либо внешней объвязки. Поэтому что-бы для проверки, достаточно подключить ардуину, залить скетч, открыть сериал монитор (убедится что скорость 9600), и послать ардуине букву r.После чего,  у нас на секунду загорится светодиод.

Artur1985
Offline
Зарегистрирован: 19.02.2013

lenon пишет:

спасибо большое.как все соберу отпишусь и раскажу как все прошло


Так а я ни чего не сделал, еще.

Только добрался, минут через 30 гляну.

Artur1985
Offline
Зарегистрирован: 19.02.2013

Сделал бы немног по другому.
Массив ножек
 

#define pinArraySize 3 // Размер массива ножек
const byte pinArray[pinArraySize] = { 1, 2, 3}; // Массив ножек

Настроил бы их в setup так
 

for( i = 0; i < pinArraySize; ++i )
  {
    pinMode(pinArray[i],OUTPUT);  
  }

В начале loop
Вставил бы следующие
 

if (!Serial.available())
{
    return;  // Если данных нет, прерываем loop

}
else
{
     char choiseComp = Serial.read(); 
    
     switch(choiseComp)
     {
  	      case '1':
            // 1 комп.
            raiseResetCom(0);
            break;
          case '2':
            // 2 комп.
            break;
          default:
            // Что-то не так
            break;
     }
}

Пределал бы функцию raiseReset 
 

void raiseReset(int selectComp)
{
   Serial.print("RESET....");;
   digitalWrite(pinArray[i],HIGH); // дали 5-ть вольт на пин
   delay(PULSE_TIME);// подождали
   digitalWrite(pinArray[i],LOW);  // выключили

   Serial.println("DONE");
}

delay конечно не есть хорошо, но тут пойдет

Artur1985
Offline
Зарегистрирован: 19.02.2013
void clearSerialInput(){
  while(Serial.available())Serial.read();
}

Я так и не понял зачем, ни разу не использовал такое, мне кажется это лишнее.

UPD. Убегаю, постараюсь вечером глянуть.

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

Я сознательно сделал вначале "упрощенный вариант". Вначале для одного пина.... а потом уже усложнять можно. Когда проверенно и работает. Agile методики нынче в моде ;)

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

Да и от delay избавится не так уж и трудно... тем более что вероятность когда "нужно ребутнуть сразу все" - тоже не нулевая.

Вот в таком варианте добавить/убрать пин требует изменений только в одном месте: массив pins. Просто "дописать еще один". И все.

#define PULSE_TIME 1000 // сколько времени будет high генерить, в миллисекундах

byte pins[]={13,9};
#define TOTAL_PINS sizeof(pins)/sizeof(byte) // вычисляем сколько всего у нас пинов

unsigned long on_times[TOTAL_PINS]; // массив где мы будем хранить время включения пинов


void setup(){
  Serial.begin(9600);
  for(byte i=0;i<TOTAL_PINS;i++){
    pinMode(pins[i],OUTPUT); // включаем все пины на выход
    on_times[i]=0; // на всякий случай обнуляем массив
  }
  

  printReady();
}

void printReady(){
  Serial.println("Ready");
  Serial.println("Send ");
  for(byte i=0;i<TOTAL_PINS;i++){
    Serial.print(i+1,DEC);
    Serial.print(" to reset on pin ");
    Serial.println(pins[i],DEC);
  }

  
}

void loop(){
  
  if(Serial.available()){
      byte pinIndex=Serial.read()-'0'-1; // -1 для перевода из "человеческого", в zero-based индексацию
      if(isValidPinNo(pinIndex)){ // что-то делаем только для правильных индексов, все остальное - игнорируем
         raiseReset(pinIndex);
      }
  }
  
  offPins(); // смотрим кого пора выключить
}

bool isValidPinNo(byte pinIndex){ // возвращает true если индекс пина правильный. 
   return pinIndex>=0 && pinIndex<TOTAL_PINS;
}



void raiseReset(byte outPinIndex){
    setPinState(pins[outPinIndex],HIGH); // включили 5v на пин
    on_times[outPinIndex]=millis();// запомнили когда включили


   Serial.println("DONE");
}

void setPinState(byte pinNo,bool pinState){ // включает пин и сообщает об этом в Serial
   Serial.print(millis());
   Serial.print(": pin ");
   Serial.print(pinNo);
   Serial.print("set to ");
   Serial.println(pinState?"HIGH":"LOW");
   digitalWrite(pinNo,pinState);
}



void offPins(){ // смотрим кого пора выключить
  for(byte i=0;i<TOTAL_PINS;i++){
      if( on_times[i] && (millis()-on_times[i])>=PULSE_TIME){ // пин включен и пришло время его выключать
          setPinState(pins[i],LOW);// выключает пин и сообщает об этом в сериал
         on_times[i]=0; // отметили что пин выключен
     }
  }
}

 

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

Artur1985 пишет:

void clearSerialInput(){
  while(Serial.available())Serial.read();
}

Я так и не понял зачем, ни разу не использовал такое, мне кажется это лишнее.

UPD. Убегаю, постараюсь вечером глянуть.

Это "дело вкуса". Такая себе "защита от залипания". Учитывая что там у нас был delay(). А то нажмет человек, неглядя... send раз 20-ть (в какой-нибудь терминальной программе которая после отсылки не ощичает input стринг)  а потом жалуется "ой... чтото оно целую минуту не выключается....". Ну и... просто как способ проигнорить переводы строк и проч. случайный мусор. Реализация "выполняем только одну команду за раз". Вообщем повышение "предсказуемост" и "быть всегда готовым выполнить команду". Но в принципе, вы правильно заметили... не обязательно. Делать именно так :)

Artur1985
Offline
Зарегистрирован: 19.02.2013

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

Ой я в суматохе не сразу заметил другого, подумав, что все пишет lenon, редко на этом форуме. А логины начинаются одинаково.

leshak пишет:
Отличие только в мелочах... ну не люблю я руками считать размер массива, выписывать switch когда нужно что-то поменять и т.п. Да и от delay избавится не так уж и трудно... тем более что вероятность когда "нужно ребутнуть сразу все" - тоже не нулевая.

Да думал то же уйти от написание индекса. С delay быстро не сообразил, знал, что лучше millis().

leshak пишет:
 Это "дело вкуса". Такая себе "защита от залипания". Учитывая что там у нас был delay(). А то нажмет человек, неглядя... send раз 20-ть (в какой-нибудь терминальной программе которая после отсылки не ощичает input стринг)  а потом жалуется "ой... чтото оно целую минуту не выключается....". Ну и... просто как способ проигнорить переводы строк и проч. случайный мусор. Реализация "выполняем только одну команду за раз". Вообщем повышение "предсказуемост" и "быть всегда готовым выполнить команду". Но в принципе, вы правильно заметили... не обязательно. Делать именно так :)

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

Спасибо за пояснение.
 

Artur1985
Offline
Зарегистрирован: 19.02.2013

Внимательно посмотрел код leshak красота

Попробую и свой код переделать без этого костыля delayMicroseconds(100), если получится. 
Большое спасибо, за разъяснения.

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

Ну delayMicroseconds(100) - возможно и не обязательно убирать. "На глаз" их ощутить сложно. Иллюзия одновремености может возможно сохранится и без убирания delayMicroseconds().  А код с ними получается намного проще. Так что "это не догма". Выкидывать delay() везде где только возможно - совсем не обязательно. Плюс к этому, подход чере millis() - он как-бы "приблизительный".  millis()-ontime>=INTEVAL срабатывает "приблизительно". Имеет погрешность. В случае "микросекунд", эта погрешность уже может быть с ними сопоставима. Так что тут еще по задаче смотреть нужно.

Artur1985
Offline
Зарегистрирован: 19.02.2013

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

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

Сам delayMicroseconds появился из-за скорости в 115200, подбирал вручную, передаю строки. Однако начал играться с CodeVisionAVR и понял, что при таких скоростях есть вероятность потери данных. Теперь смотрю в сторону уменьшения.

Поэтому и начали писать систему контроля передачи данных, с подтверждением, проверкой строки и синхронизацией номера строки. Уже написали болванку, осталось отловить 1 ошибку и оптимизировать жирно получилось 600 строк (видимо не талант:)), хоть и большая часть это коменты.

UPD. Надеюсь у Вас lenon все получается.

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

Artur1985 пишет:

Сам delayMicroseconds появился из-за скорости в 115200, подбирал вручную, передаю строки. Однако начал играться с CodeVisionAVR и понял, что при таких скоростях есть вероятность потери данных. Теперь смотрю в сторону уменьшения.

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

Artur1985
Offline
Зарегистрирован: 19.02.2013

leshak пишет:

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

Ясно, значит уберем. Просто потребуется повозится именно из-за ошибки проектирования.

Большое спасибо, что указали на ошибку. Когда когда знаешь где копать, все становится проще.

UPD. Уже обрабовал коллегу, что надо будет поменять схему, он без колебаний согласился. Он ведет описание кусочка проекта тут http://forum.amperka.ru/threads/%D0%A1%D0%B2%D1%8F%D0%B7%D1%8C-%D1%81-%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D0%B5%D0%BC-%D0%B8-%D1%81%D0%B8%D0%BD%D1%85%D1%80%D0%BE%D0%BD%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B5%D0%B9-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.2699/

Код пока еще сырой.

UPD 2.
Не знал, что так можно
 

if( on_times[i] && (millis()-on_times[i])>=PULSE_TIME){ // пин включен и пришло время его выключать
          setPinState(pins[i],LOW);// выключает пин и сообщает об этом в сериал
         on_times[i]=0; // отметили что пин выключен
     }

Говорю о on_times[i], думал, что только так on_times[i] > 0

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

>Он ведет описание кусочка проекта тут

Для скачивания сырцов там надо регатся... а мне влом... если честно то и скачивать влом. Лучше дайте тут. Вернее лучше конечно отдельную ветку, что-бы это не хламить "всем подряд", с сюда просто ссылочку на новую ветку. Сделать, так сказать ответвление.

>Говорю о on_times[i], думал, что только так on_times[i] > 0

Можно и как вы пишите. А можно и как я.... в качестве boolean можно использовать переменную/выражение ЛЮБОГО типа (byte,int, ссылки/указатели и т.п.) . Если переменная равна нулю - она будет интерпретирована как false, если не равна как true.

Artur1985
Offline
Зарегистрирован: 19.02.2013

leshak пишет:

>Он ведет описание кусочка проекта тут

Для скачивания сырцов там надо регатся... а мне влом... если честно то и скачивать влом. Лучше дайте тут. Вернее лучше конечно отдельную ветку, что-бы это не хламить "всем подряд", с сюда просто ссылочку на новую ветку. Сделать, так сказать ответвление.

Увы там не помещалось в редакторе, сам не люблю такого. Да Вы правы сделаю в отдельную ветку. В понедельник, много работы.

Жду когда получится у lenon, стараюсь не оставлять ветку где отвечаю. Хотя Вы уже предложили отличный вариант.

leshak пишет:

Можно и как вы пишите. А можно и как я.... в качестве boolean можно использовать переменную/выражение ЛЮБОГО типа (byte,int, ссылки/указатели и т.п.) .

Не знал, спасибо.

Artur1985
Offline
Зарегистрирован: 19.02.2013

Поступил, как Вы советовали, создал отдельную ветку
http://arduino.ru/forum/proekty/kontrol-peredachi-dannykh