среда, 8 ноября 2023 г.

VanLife первый опыт.

Давно хотел попробовать дом на колёсах. И вот дождавшись холодов (температура воздуха околонулевая), чтобы аренда автодома имела хоть какой-то смысл в скравнении с палаткой в багажнике, мы арендовали кемпер и отправились в небольшое путешествие. Тягач у нас был - пожилой ланос и исдыхающим мотором, по-этому, поехать решили совсем недалеко - примерно 100 км от дома на мыс Флотский.

Прицеп категории 750 кг. Рассказывали, что такой возили в сочи на приоре и благополучно вернулись. Масса автомобиля документально - 1220 кг. Задние пружинны заменены летом, и им тяжело. На кочках несколько раз пробило подвеску. Ехать приходилось на повышенных оборотах и трогаться с обильным использованием сцепления. Я Пререживал, что не доедем.

В Левашово, там где всегда затор на повороте налево, да ещё и в некрутую горку стало совсем плохо: холостые стали неустойчивыми, даже заглох разок. Но потом пробок не было и доехали нормально.


По пути нам надо было заправить воду. На АЗС ГазпромНефть местной лейкой залил 75 литров. Взяли в канистру ДТ для отопителя и поехали дальше.


И вот мы приехали на место нашей стоянки. Погуляли по пляжу и насладились красивыми видами.

Вечер провели в домике.
Спали под урчание отопителя. Звуковая обстановка напоминала поезд. Как-будто стоит на станции и вот-вот поедет. Только кровати длинее и удобнее: ноги никуда не упираются и не свисают. Если выйти наружу или выглянуть из люка или окна, можно позалипать на море и светящиеся суда на форваторе. Объём помещения маленький, а отопитель у нас был мощный для морозов. С жарой и духотой справлялись открытыми вытяжкой и люком, и это на минимальной мощности отопителя. 

На следущий день поехали налегке (без прицепа) в город Приморск. Посетили камень Мамонт
берег залива
кирху
Сходили к причалу ледокола Ленин
Пока ходили вдоль берега, пришёл кот.
Вечером обнуружили, что вода (бак 75 литров) почти закончилась, т.к. ещё не привыкли экономить. Но тары, в которой мы могли бы её привезти всё равно не было, а ехать специально за водой с прицепом не хотелось. В режиме экономии нам воды хватило. Последний литр вскипятили и залили в термос.

На следующий день собрались, и отправились в сторону дома, совершив прогулку на пляже Ласковый.



Кое-как вернулись домой на пердящем потребляющим нереальное количество масла (а обороты всегда повышены) с пахнущим сцеплением тягаче. Вот фото воздушной заслонки после такого путешествия.
Итог. Несмотря на то, что наш автомобиль однозначно не подходит для буксировки такого тяжёлого прицепа, поездкой мы остались довольны. Жить на природе при уже холодной погоде с двумя детьми в таком автодоме вполне комфортно. Хотя, конечно, летом обычная палатка в багажнике, на плечах или плавсредстве несравнено дешевле и универсальнее.
Хотелось бы когда-нибудь поехать подальше и на подольше на более тяжёлом тягаче.

пятница, 11 января 2019 г.

Таймер-Терморегулятор для аквариума/террариума

Здравсвуйте, представляю вашему вниманию проект на Arduino. Террариум, в котором живёт черепаха. Наше устройство служит для выполнения следующих задач:
1) включение и выключение лампы по расписанию (день-ночь);
2) поддержание температуры в террариуме путём включения и выключения нагревательного элемента;
3) отображение текущего времени суток и температуры воды в террариуме на четырёхсекционном светодиодном семисегментном дисплее (хорошо видно днём и ночью, выполняют функцию настенных часов), яркость дисплея меняется в зависимости от сотояния "день/ночь";
4) Все необходимые пользователю настоечные параметры (уставка температуры, гистерезис, первый и последний часы дня, текущее время) возможно легко задавать без подключения к ПК или иным устройствам, то есть с кнопок.
Вот результат решения этой задачи

Для этого проекта я использовал модули:
Arduino Pro Mini (ATmega328, 5В)
Реле э/м 1-канальное, 5В - 2 шт. Рекомендую вместо них использовать Реле электромеханическое 2-канальное - 1 шт.
Модуль часов реального времени DS1307
Цифровой дисплей TM1637
Кнопка - 4 шт.
термистор
резистор 10 кОм - пачка :)

Схему соединения выложу позже. Назначения пинов ясно из деректив #define в начале кода. Незабываем кнопки (включая reset) и термистор подключать с использованием резисторов.

программный код:
#include
#include
#include
#include
#include
#include

//номера пинов
#define LIGHT 2
#define TEN 3
#define DISPLAY_CLK 4
#define DISPLAY_DIO 5
#define BUTTON_MODE 9
#define BUTTON_MINUS 7
#define BUTTON_PLUS 8
// **************

//количество режимов настройки
#define MIN_TUNER_MODE 2
#define MAX_TUNER_MODE 6
#define TIMEOUT 10
// **************

//адрес настроек в Eeprom
#define EE_ADDRESS 0
// **************

class Timer
{
  long int start_time;
public:
  void start()
  {
    start_time = millis();
  }
  int seconds()
  {
    return (int)((millis() - start_time)/1000);
  }
  long int miliseconds();
  Timer()
  {
    start();
  }
};

struct Settings
{
  float temp_ust,temp_hyst;//температура, поддерживаемая в аквариуме, гистерезис
  int time_light_on,time_light_off;//время включения и выключения света
};

Settings settings;
int8_t DispMSG[] = {10, 16, 31, 6};
TM1637 clock_diplay(DISPLAY_CLK, DISPLAY_DIO);
bool ten_on=false;
Timer notclick;

double Thermister(int RawADC) {
  double Temp;
  Temp = log(((10240000/(1024-RawADC)) - 10000));
  Temp = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temp * Temp ))* Temp );
  Temp = Temp - 273.15;   // Kelvin to Celcius
  //Temp = (Temp * 9.0)/ 5.0 + 32.0;    // 1 способ Convert Celcius to Fahrenheit
  //Temp = (Temp * 1.8) + 32.0;   // 2 способ Convert Celcius to Fahrenheit
  return Temp;
  /*
  float RT, VR, ln, TX, T0;
  int VRT;
  VRT=RawADC;
  VRT = (5.00 / 1023.00) * VRT;      //Преобразуем в напряжение
  VR = VCC - VRT;
  RT = VRT / (VR / R);               //Сопротивление RT

  ln = log(RT / RT0);
  TX = (1 / ((ln / B) + (1 / T0))); //Температура с термистора

  TX = TX - 273.15;                 //Преобразуем в цельсии
  return TX;*/
}


void show_error(int8_t err_num)
{
  DispMSG[0] = 14;
  DispMSG[1] = 28;
  DispMSG[2] = 28;
  DispMSG[3]=err_num;
  clock_diplay.display(DispMSG);
  clock_diplay.point( false );
}


void relaySet(tmElements_t tm_)
{
  if( (tm_.Hour >= settings.time_light_on)&&(tm_.Hour <= settings.time_light_off ) )
  {
    digitalWrite(LIGHT, LOW);
    Serial.println("Light ON");
    clock_diplay.set(7);
  }
  else
  {
    digitalWrite(LIGHT, HIGH);
    Serial.println("Light OFF");
    clock_diplay.set(1);
  }

  if( ten_on )
  {
    if (float(Thermister(analogRead(0)))> settings.temp_ust+settings.temp_hyst )
      ten_on=false;
    digitalWrite(TEN, LOW);
    Serial.println("TEN ON");
  }
  else
  {
    if (float(Thermister(analogRead(0))) < settings.temp_ust-settings.temp_hyst )
      ten_on=true;
    digitalWrite(TEN, HIGH);
    Serial.println("TEN OFF");
  }
}

void clockDispSet(tmElements_t tm_)
{
  if((tm_.Second%10)>4)
  {
  DispMSG[0]=tm_.Hour/10;
  DispMSG[1]=tm_.Hour%10;
  DispMSG[2]=tm_.Minute/10;
  DispMSG[3]=tm_.Minute%10;
  clock_diplay.display(0,DispMSG[0]);
  clock_diplay.point( ((tm_.Second%2)>0) );
  clock_diplay.display(1,DispMSG[1]);
  clock_diplay.display(2,DispMSG[2]);
  clock_diplay.display(3,DispMSG[3]);
  }
  else
  {
    int temp=int(Thermister(analogRead(0)));
    DispMSG[0]=temp/10;
    DispMSG[1]=temp%10;
    DispMSG[2]=33;//17;
    DispMSG[3]=12;
    clock_diplay.point( false );
    clock_diplay.display(DispMSG);
  }
}

void mode1() {
  tmElements_t tm;
  Serial.print("Sensor_0: ");
  Serial.println(float(Thermister(analogRead(0))), 1);    // выводим показание 1 датчика

  if (RTC.read(tm)) {
    Serial.print("Time = ");
    Serial.print(tm.Hour);
    Serial.write(':');
    Serial.print(tm.Minute);
    Serial.write(':');
    Serial.print(tm.Second);
    Serial.print(", Date (D/M/Y) = ");
    Serial.print(tm.Day);
    Serial.write('/');
    Serial.print(tm.Month);
    Serial.write('/');
    Serial.print(tmYearToCalendar(tm.Year));
    Serial.println();
    relaySet(tm);
    clockDispSet(tm);
  } else {
    setHour();
    Serial.println("There are problem whith DS1307RTC");
    if (RTC.chipPresent()) {
      Serial.println("The DS1307 is stopped.  Please run the SetTime");
      Serial.println("example to initialize the time and begin running.");
      Serial.println();
    } else {
      Serial.println("DS1307 read error!  Please check the circuitry.");
      Serial.println();
    }
    delay(9000);
  }

}

void show_mode(int mode)
{
  tmElements_t tm;
  switch(mode)
  {
    case -1: DispMSG[0] = 17;  DispMSG[1] = 17; clock_diplay.point( false ); DispMSG[2] = 17;  DispMSG[3] = 17;  break;
    case 2:  DispMSG[0] = 29;  DispMSG[1] = 33; clock_diplay.point( true ); DispMSG[2] = (int)settings.temp_ust/10;  DispMSG[3] = (int)settings.temp_ust%10;  break;
    case 3:  DispMSG[0] = 20;  DispMSG[1] = 29; clock_diplay.point( true );  DispMSG[2] = (int)settings.temp_hyst;  DispMSG[3] = (int)(10*settings.temp_hyst)%10; break;
    case 4:  DispMSG[0] = 34;  DispMSG[1] = 17; clock_diplay.point( true );  DispMSG[2] = settings.time_light_on/10;  DispMSG[3]=settings.time_light_on%10;break;
    case 5:  DispMSG[0] = 36;  DispMSG[1] = 17; clock_diplay.point( true );  DispMSG[2] = settings.time_light_off/10;  DispMSG[3]=settings.time_light_off%10;break;
    case 6:  DispMSG[0] = 29; DispMSG[1] = 21; clock_diplay.point( false ); DispMSG[2] = 26; DispMSG[3] = 14; break;
/*
    case 6:
      DispMSG[0] = 25;  DispMSG[1] = 25; clock_diplay.point( true );
      if (RTC.read(tm)) { DispMSG[2] = tm.Minute/10;  DispMSG[3] = tm.Minute%10;}
      else { DispMSG[2] = 0;  DispMSG[3]=0;}
      break;
    case 7:
      DispMSG[0] = 19;  DispMSG[1] = 17; clock_diplay.point( true );
      if (RTC.read(tm))
      {
        DispMSG[2] = tm.Hour/10;
        DispMSG[3] = tm.Hour%10;
      }
      else { DispMSG[2] = 0;  DispMSG[3]=0;}
      break;
      */
  }
  clock_diplay.display(DispMSG);

}

void show_float(float f)
{
  DispMSG[0]=(int)f/10;
  DispMSG[1]=(int)f%10;
  DispMSG[2]=35;
  DispMSG[3]=(int)(f*10)%10;
  clock_diplay.display(0,DispMSG[0]);
  clock_diplay.point( false );
  clock_diplay.display(1,DispMSG[1]);
  clock_diplay.display(2,DispMSG[2]);
  clock_diplay.display(3,DispMSG[3]);

}

void setFloat(float *var,float minimum,float maximum)
{
  Serial.println("Set float");
  show_float(*var);
  Serial.println(*var);
  delay(500);
  while( (digitalRead(BUTTON_MODE) == LOW) &&(notclick.seconds()  {
    if(digitalRead(BUTTON_PLUS) == HIGH)
    {
      notclick.start();
      *var = (*var) + 0.1;
 //     if( (*var)>maximum )
 //       (*var) = minimum;
      Serial.println(*var);
      show_float(*var);
      delay(250);
    }
    if(digitalRead(BUTTON_MINUS) == HIGH)
    {
      notclick.start();
      *var = (*var) - 0.1;
      if( (*var)< minimum )
        (*var) = maximum;
      Serial.println(*var);
      show_float(*var);
      delay(250);
    }
  }
}

void show_int(int dm0,int dm1,int var)
{
  DispMSG[0]=dm0;
  DispMSG[1]=dm1;
  DispMSG[2]=var/10;
  DispMSG[3]=var%10;
  clock_diplay.display(0,DispMSG[0]);
  clock_diplay.point( true );
  clock_diplay.display(1,DispMSG[1]);
  clock_diplay.display(2,DispMSG[2]);
  clock_diplay.display(3,DispMSG[3]);

}

void setInt(int dm0,int dm1,int *var,int minimum,int maximum)
{
  Serial.println("Set int");
  show_int(dm0,dm1,*var);
  delay(500);
  while(( digitalRead(BUTTON_MODE) == LOW)&&(notclick.seconds()  {
    if(digitalRead(BUTTON_PLUS) == HIGH)
    {
      notclick.start();
      (*var)++;
      if( (*var)>maximum )
        (*var) = minimum;
      show_int(dm0,dm1,*var);
      Serial.println(*var);
      delay(250);
    }
    if(digitalRead(BUTTON_MINUS) == HIGH)
    {
      notclick.start();
      (*var)--;
      if( (*var)< minimum )
        (*var) = maximum;
      show_int(dm0,dm1,*var);
      Serial.println(*var);
      delay(250);
    }
  }
}


void setTemp()
{
  float temp = settings.temp_ust;
  setFloat(&temp,10,40);
  settings.temp_ust = temp;
  EEPROM.put(EE_ADDRESS, settings);
}

void setHyst()
{
  setFloat(&(settings.temp_hyst),0.1,3);
  EEPROM.put(EE_ADDRESS, settings);
}

void setTimeLightOn()
{
  setInt(0,26, &(settings.time_light_on),0,23 );
  EEPROM.put(EE_ADDRESS, settings);
}

void setTimeLightOff()
{
  setInt(0,15, &(settings.time_light_off),0,23 );
  EEPROM.put(EE_ADDRESS, settings);
}

void setHour()
{
  tmElements_t tm;
  int h,m;
  if(RTC.read(tm))
  {
    h = tm.Hour;
    m = tm.Minute;
  }
  else
  {
    h = 12;
    m = 0;
  }
  setInt(19,17,&h,0,23);
  setInt(17,17,&m,0,59);
  tm.Hour = h;
  tm.Minute = m;
  tm.Second = 0;
  tm.Day = 1;
  tm.Month = 1;
  tm.Year = 18;

  RTC.write(tm);
}

void mode2()
{
 int mode=MIN_TUNER_MODE;//переменная выбора режима
 show_mode(-1);
 delay(500);
 while( (mode<=MAX_TUNER_MODE)&&(notclick.seconds() {
  if(digitalRead(BUTTON_MODE) == HIGH)
  {
    notclick.start();
    mode++;
    show_mode(-1);
    delay(500);
  }
  if ( (digitalRead(BUTTON_PLUS) == HIGH) || (digitalRead(BUTTON_MINUS) == HIGH) )
  {
    notclick.start();
    switch(mode)
    {
      case 2: setTemp();break;
      case 3: setHyst();break;
      case 4: setTimeLightOn();break;
      case 5: setTimeLightOff();break;
      case 6: setHour();break;
    }
  }

  Serial.print("mode: ");
  Serial.println(mode);
  show_mode(mode);
 }
}

void print2digits(int number) {
  if (number >= 0 && number < 10) {
    Serial.write('0');
  }
  Serial.print(number);
}





void loop()
{
  if(digitalRead(BUTTON_MODE) == LOW)
  {
    mode1();
  }
  else
  {
    notclick.start();
    mode2();
  }
}

void setup() {
  Serial.begin(9600);
  while (!Serial) ; // wait for serial
  delay(200);
  Serial.println("Akvarium v6 geting settings and testing.");
  Serial.println("-------------------");

  EEPROM.get(EE_ADDRESS, settings);
  if( !( (settings.temp_ust > -50. )&&(settings.temp_ust < 100. ) ) )
  {
    Serial.println("install default settings.");
    settings.temp_ust = 22;
    settings.temp_hyst = 1;
    settings.time_light_on=9;
    settings.time_light_off=21;
    EEPROM.put(EE_ADDRESS, settings);
  }

  clock_diplay.init();
  //Установка яркости горения сегментов
  /*
   * BRIGHT_TYPICAL = 2 Средний
   * BRIGHT_DARKEST = 0 Тёмный
   * BRIGHTEST = 7      Яркий
   */
  clock_diplay.set(BRIGHT_TYPICAL);
  //Задание на включение разделителя
  clock_diplay.point(true);
  //Выводим массив на дисплей
  clock_diplay.display(DispMSG);
  pinMode(LIGHT, OUTPUT);
  pinMode(TEN, OUTPUT);
  pinMode(A0, INPUT);
  pinMode(BUTTON_MODE, INPUT);
  pinMode(BUTTON_MINUS, INPUT);
  pinMode(BUTTON_PLUS, INPUT);
/**/
  digitalWrite(LIGHT, LOW);
  delay(1500);
  digitalWrite(LIGHT, HIGH);
  delay(1500);
  /**/

}

четверг, 18 июня 2015 г.

Поход к церкви Николы на Липне

            В этом посту я повествую о своём первом опыте одиночного похода выходного дня. Путешествовал я совсем недалеко (около 10 км от кремля) от города Великий Новгород. Однако из-за болот и большого количества рек этот район почти необитаем людьми.
            Путешествовал я с видео-камерой. На в момент написания рассказа (наброски я сделал уже в походе) видео в монтаже.
             День первый. Вечер пятницы. Вышел на берег Сиверсова канала. Дорога вдоль берега заболочена. Немного прошёл вдоль и встал напротив деревни Сковородка. За всё время пребывания на этой стоянке я видел только одного пешехода: парень с удочкой.
Сиверсов канал

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

за переправой
           Дальше началась основная часть похода. При помощи навигации и интуиции нашёл что-то напоминающее на заброшенную дорогу и пошёл по этой Козловой дороге (так называют её местные жители) или вдоль неё (не везде я мог однозначно сказать, что когда-то здесь была дорога). Сначала был густой лес с крупными деревьями, потом - поле, затем - вышел в болото, которое явно когда-то было дорогой. Шёл по этой бывшей дороге по плавучим кочкам ("второе дно") и корням по краям. Проваливался сначала по колено, потом - по пояс. Стоит отметить то, что я не взял с собой вторые штаны для экономии веса. В конце этой части пути увидел между деревьев купол. Стоит отметить, что к тому моменту я уже подустал и обрадовался близости цели, однако радость моя была недолгой. За "Черным лесом" (так это место называют местные) оказался заболоченный луг и озеро, в середине которого церковь.
Козлова дорога в Черном лесу

Стала видна конечная точка маршрута
"...За "Черным лесом" (так это место называют местные) оказался заболоченный луг и озеро, в середине которого церковь."
                Пришлось обходить по лугу. Воды примерно по колено. перешейка между мной и церковью не видно, но на карте (Яндекс народная) обозначена дорога. Нашёл место, где перейти с берега на остров. Там оказалось примерно по пояс. И пошёл по такому же лугу к церкви. Подойдя поближе увидел большое количество рыболовных сетей, заготовленные чурбаны и женщину, коловшую дрова.
Осталось ещё чуть-чуть
                Подошёл к женщине и сказал: "Здравствуйте!" Она: "Ой!" Тут выбежали две собаки и ко мне, я от них и баллончик перцовый выпустил, на который они (собаки) не отреагировали. Женщина зовёт собак, а они не уходят. Кричит мне:
 - Через 20 минут Леонид приедет.
 - И можно будет переночевать здесь?
 - Какой переночевать! Тут церковь!
 - Я в палатке на острове!
 - Вон там, где песочек можно встать, - и показывает, куда идти.
Собаки на по-тихоньку наступают, я - отступаю. Уже в болото полезли. Защищаться от собак мне нечем.
                Пришёл на то место, куда мне указала женщина. Там людские следы: костер тлеет (совсем недавно кто-то ушёл отсюда), дрова приготовлены. Добавил огня, стал сушиться, котелок поставил. Подъезжает лодка. В ней три мужика. Я в трусах, вещи по поляне раскиданы, что-то у костра сушится. Один мужик выходит ко мне:
 - Это тебя собаки...
 - Это меня собаки выгнали.
Рассказываю, что я турист, пришёл пешком. А он мне: "Пришёл! Пешком! По болоту! Вам там в городе совсем делать нечего... чего вам перед телевизором дома не сидится!" Я не стал объяснять, почему мне пред зомбоящиком не сидится. Видимо много туристов их посещать стало (геокешерский тайник заложен в 2006. я ходил в 2015). Надоели им гости.
"Подсушился, поел я и лёг спать."

                Подсушился, поел я и лёг спать. На следующий день предстоит без штанов идти (у меня одни, сушить будет некогда). Планирую возвращаться тем же маршрутом. Важно найти начало Козловой дороги. Место где я вышел, на несколько десятков метров отличается от обозначенного на карте.
Ближе я не подошёл

                День третий. Воскресение. Встал, позавтракал, собрался, пошёл. Дорогу по которой я шёл так и не нашёл, хотя был где-то очень близко. Пейзаж на обратном пути через "Черный лес" заметно отличался: лес на болоте. В поле увидел примятую трактором (наверное) калею и пошёл по ней. Дорога, теперь уже действующая, вывела меня на берег Сиверсова канала как раз в район деревни Сковородка. До берега немного болота, но я уже к тому времени привык. Потом рыбаки переправили меня на берег с цивилизацией. До трассы Новгород-Москва можно было дойти пешком, но мне повезло застопить попутку до Новгорода.
путь обратно
С этой остановки начался поход.
на обратном пути