Перейдем сразу к делу:

ArduinoIR

И машинка, и пульт дистанционного управления будут работать под управлением Arduino Uno. На схеме они обозначены Transmitter и Reciever. На передатчике у нас будет потенциометр для регулировки скорости движения, и кнопка для регулировки направления: вперед или назад. Пока что без поворотов. На приемнике у нас будет все тот же H-мост L293D и один моторчик, который будет крутить задние колеса. К сожаление, в Proteus нельзя добавить радио-приемник и передатчик, поэтому их будет симулировать провод, соединяющий 13-е порты Ардуин.
Перейдем к самой сложной части системы — шифрованию и дешифровке сигнала. Будем использовать термин «отсчет», который будет означать переполнение таймера. Начало посылки будет длиться 400 отсчетов, затем 255 отсчетов для регулировки скорости, 50 отсчетов на интервал между скоростью и направлением, и 255 отсчетов для регулировки направления. Скорость будет регулироваться ШИМ-сигналом. Насчет направления будем считать, что 255 означает вперед, 127 — назад, или наоборот.

сигнал

Для упрощения работы с таймером будем использовать библиотеку TimerOne. Далее приведен полный код приемника и передатчика с некоторыми комментариями:

// Передатчик
#include <TimerOne.h>

const int infra_red_pin = 13;
const int direction_pin = 3;
const int potentiometer_pin  = A0; 

int direction_of_motion;
int counter_cycles;
int m_speed = 0;

const int timer1_period = 1000; // Значение для переполнения мкс
const int package_start = 400;
const int package_gap = 50;

void setup() {
  pinMode(infra_red_pin, OUTPUT);
  pinMode(direction_pin, INPUT);
  pinMode(potentiometer_pin, INPUT);

  Timer1.initialize(timer1_period);
  Timer1.attachInterrupt(blinky);
}

void loop() {
  if (digitalRead(direction_pin)) {
    direction_of_motion = 127;
  }
  else {
    direction_of_motion = 255;
  }

  m_speed = map(analogRead(potentiometer_pin), 0, 1023, 0, 255);
}

// Обработка прерываний по таймеру
void blinky()
{
  if (counter_cycles == package_start) {
    digitalWrite(infra_red_pin, HIGH);
  }
  if (counter_cycles == (package_start + m_speed)) {
    digitalWrite(infra_red_pin, LOW);
  }

  if (counter_cycles == package_start + 255 + package_gap) {
    digitalWrite(infra_red_pin, HIGH);
  }
  if (counter_cycles == (package_start + 255 + package_gap + direction_of_motion)) {
    digitalWrite(infra_red_pin, LOW);
  }

  counter_cycles++;
  if (counter_cycles > package_start + (2 * 255) + package_gap) {
    counter_cycles = 0;
  }
}

// Приемник
#include <TimerOne.h>

const int infra_red_pin = 13;
const int motor_b1 = 10;
const int motor_b2 = 11;

int counter_cycles;
int m_speed = 200;

const int timer1_period = 1000; // Значение для переполнения мкс
const int package_start = 400;

void setup() {
  pinMode(infra_red_pin, INPUT);
  pinMode(motor_b1, OUTPUT);
  pinMode(motor_b2, OUTPUT);

  Timer1.initialize(timer1_period);
  Timer1.attachInterrupt(blinky);
}

void loop() {
  // ждем начала пакета
  while(digitalRead(infra_red_pin)!=0);
  counter_cycles = 0;
  while(digitalRead(infra_red_pin)!=1);

  if (counter_cycles < 400) return; //Если пауза не выдержана...

  // считываем скорость
  while(digitalRead(infra_red_pin)!=0);
  m_speed = counter_cycles;

  // считываем направление
  while(digitalRead(infra_red_pin)!=1);
  counter_cycles = 0;
  while(digitalRead(infra_red_pin)!=0);

  if(counter_cycles < 50){
    stop_car();
  }else if(counter_cycles < 150){
    forward();
  }else{
    backward();
  }

  counter_cycles = 0;
}

// Обработка прерываний по таймеру
void blinky()
{
  counter_cycles++;
}

// Остановиться
void stop_car(){
  analogWrite(motor_b1, LOW);
  analogWrite(motor_b2, LOW);
}

// Едем вперед
void backward(){
  analogWrite(motor_b1, m_speed);
  analogWrite(motor_b2, LOW);
}

// Едем назад
void forward(){
  analogWrite(motor_b1, LOW);
  analogWrite(motor_b2, m_speed);
}

Реклама

В прошлой части было рассказано как сделать радиоуправляемую машинку с использованием ATtiny2313 на языке ассемблер. Теперь давайте посмотрим как ее можно сделать с использованием Arduino. Возьмем самую популярную модель Arduino Uno. Она хороша тем, что в ней есть АЦП. Его мы будем использовать для регулировки скорости движения. Сама регулировка будет осуществляться с помощью обычного потенциометра. Еще хотелось бы управлять такой машинкой дистанционно, например через последовательный порт компьютера, но тогда нам нужен будет провод, или через Bluetooth мобильного телефона. В Proteus есть замечательная вещь, которая называется «Виртуальный терминал», он нам заменит оба этих случая, достаточно только подключить RX с TX и наоборот. Теперь можно считать, что либо мы протянули длинный провод от компьютера, либо поставили на Arduino какой-нибудь Bluetooth shield или HC-05 модуль. Во втором случае можно даже написать простенькую программку для смартфона под управлением ОС Android или, зная команды, которые мы сейчас придумаем, просто скачать любой bluetooth терминал.
Схема в Proteus будет выглядеть следующим образом:
ArduinoBluetooth
В качестве H-моста используется все тот же L293D. По-хорошему, скорость тоже надо бы передавать через блютуз, но, чтобы продемонстрировать работу АЦП, сделаем такую химеру, где направление движения передается от пульта, а скорость регулируется на самой машинке. Жуть, но с такими примерами программисты сталкиваются практически каждый день 😉 Еще хорошо было бы добавить второй мотор для возможности поворачивать, но тут очень сильно зависит от конструкции самой машинки: либо как трактор будет управляться включением только одной гусеницы, либо серводвигатель будет поворачивать специальную конструкцию. Так что пока ограничимся одним моторчиком.
Система команд будет следующая:
«f» — вперед
«b» — назад
«s» — стоп
Простенький скетч для ардуино

const int pot_pin  = A0;
const int motor_b1 = 10;
const int motor_b2 = 11;

int m_potentiometer = 0;
int m_speed = 0;
int m_state = 0;

void setup() {
  pinMode(pot_pin, INPUT);
  pinMode(motor_b1, OUTPUT);
  pinMode(motor_b2, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  while(m_state == -1){
    m_state = Serial.read();
  }

  m_potentiometer = analogRead(pot_pin);
  m_speed = map(m_potentiometer, 0, 1023, 0, 255);

  switch(m_state){
    case 'f' :
      forward();
      break;
    case 'b' :
      backward();
      break;
    case 's' :
      stop_car();
      break;
    default:
      break;
  }

  m_state = -1;
}

void stop_car(){
  analogWrite(motor_b1, LOW);
  analogWrite(motor_b2, LOW);
}

void backward(){
  analogWrite(motor_b1, m_speed);
  analogWrite(motor_b2, LOW);
}

void forward(){
  analogWrite(motor_b1, LOW);
  analogWrite(motor_b2, m_speed);
}

Запустим симуляцию в протеусе и будем в виртуальном терминале посылать наши команды.
Безымянный

Давайте сделаем машинку на радиоуправлении. Начнем с простого — пусть будет один моторчик на передние или задние колеса, и ездить она пока сможет только вперед или назад. Поворачивать пока не будем, для этого понадобится поставить на каждое колесо по моторчику, и поворачивать она будет, если моторчики крутятся только с одной стороны. Пульт управления тоже сделаем попозже. Сердцем нашей машинки будет микроконтроллер ATtiny2313, в качестве Н-моста возьмем готовое решение под названием L293D. Скорость будем регулировать при помощи ШИМ, которая создается таймером 0. Вот простейшая схема в Proteus.
Безымянный
Слева находятся две кноки, собственно говоря они и управляют направление движения: верхняя — вперед, нижняя — назад. А дальше я приведу код программы на ассемблере.

.include "tn2313def.inc"

.def temp =R16
.def count =R17

.equ BT_FORWARD =PD2 ;кнопка вперед
.equ BT_BACKWARD =PD3 ;кнопка назад
.equ PWM =128

.cseg
.org 0x00
     rjmp init ;(0х00) переход на инициализацию (начальную настройку)
     rjmp go_forward ;(0х01) внешнее прерывание 0
     rjmp go_bakward ;(0х02) внешнее прерывание 1
     reti ;(0х03)
     reti ;(0х04)
     reti ;(0х05)
     reti ;(0х06)
     reti ;(0х07)
     reti ;(0х08)
     reti ;(0х09)
     reti ;(0х0A)
     reti ;(0х0B)
     reti ;(0х0C)
     reti ;(0х0D)
     reti ;(0х0E)
     reti ;(0х0F)
     reti ;(0х10)
     reti ;(0х11)
     reti ;(0х12)

.org INT_VECTORS_SIZE
init:
     ldi temp,RAMEND ;инициализация стека
     out SPL,temp

     ser temp ;порт В на выход
     out DDRB,temp
     ser temp
     out PORTB,temp

     ldi temp,(1<<PD5) ;все выводы порта D, за исключением PD5, на вход.
     out DDRD,temp ;PD5 на выход
     ser temp ;На всех выводах порта D включены подтягивающие резисторы.
     out PORTD,temp

     ;шим
     ldi temp,(1<<COM0B1|0<<COM0B0|1<<COM0A1|0<<COM0A0|1<<WGM00)
     out TCCR0A,temp
     ldi temp,(0<<CS02|0<<CS01|1<<CS00) ;деление 1
     out TCCR0B,temp ;запуск таймера

     ldi count,0
     out OCR0A,count
     out OCR0B,count

     ;1 настройка прерываний
     ldi temp,(0<<ISC01|1<<ISC00|0<<ISC11|1<<ISC10)
     out MCUCR,temp

     ;2 разрешение прерываний
     ldi temp,(1<<INT1|1<<INT0|0<<PCIE)
     out GIMSK,temp
     sei

main:
     rjmp main

;едем вперед
go_forward:
     sbic PIND,BT_FORWARD ;кнопка нажата
     rjmp stop
     ldi count,0
     out OCR0B,count
     ldi count,PWM
     out OCR0A,count
     reti

;едем назад
go_bakward:
     sbic PIND,BT_BACKWARD ;кнопка нажата
     rjmp stop
     ldi count,0
     out OCR0A,count
     ldi count,PWM
     out OCR0B,count
     reti

;ничего не нажато
stop:
     ldi count,0
     out OCR0A,count
     out OCR0B,count
     reti

Threading in C#

Posted: Ноябрь 3, 2013 in .NET
Метки:,

Allright, you may be aware that Joe Albahari is the inventor of LINQPad. Moreover he is an author of one of the finests books about .NET in general and C# in particular. Recently I was searching throuhg the Internet for a decent article about threading in C#. And first result I was getting from Google was one chapter of his C# 4.0 in a Nutshell book. Frankly it was full and comprehensive description of old threading model and TPL which was introduced in .NET 4.0. Here is a link to his page http://www.albahari.com/threading/
threading

Полезные скрипты

Posted: Август 7, 2013 in TSQL
Метки:, ,

В SSMS есть замечательная вкладка Template Explorer. Там куча скриптов почти на все случаи жизни. Простейшие скрипты можно запускать сразу. Если в скрипте есть параметры, то заходим в меню Query и выбираем Specify Values for Template Parameters. После этого указываем параметры и нажимаем ОК. Теперь скрипт с подставленными значениями тоже можно запускать.
Но эти скрипты очень многословны. Например скрипт добавления колонки занимает двадцать три строки! Из них шесть отводится только на комментарии, одиннадцать на создание таблицы %), три на собственно добавление самой колонки. Плюс несколько пустых строк. Конечно, эти скрипты скорее всего призваны быть как бы полуфабрикатами. Если что-то не нравится, то можно тут же изменить, никто нам этого не запрещает.
В процессе работы появились несколько скриптов, которые не столь тривиальны как добавление столбца. Эти скрипты используются довольно часто в наших проектах и просты в понимании:

1. Detach и Attach базы данных выглядит так


ALTER DATABASE Northwind SET OFFLINE WITH ROLLBACK IMMEDIATE
go
ALTER DATABASE Northwind SET ONLINE
go

2. Бекап и восстановление


BACKUP DATABASE Northwind TO DISK = N'C:\backups\Northwind.bak' WITH NOFORMAT, INIT, NAME = N'Northwind-Full Database Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10
GO
alter database Northwind2 set single_user with rollback immediate
go
RESTORE DATABASE Northwind2 FROM DISK = N'C:\backups\Northwind.bak' WITH FILE = 1, NOUNLOAD, STATS = 10
go
alter database Northwind2 set multi_user
go

3. Шринк


dbcc shrinkdatabase ('Northwind')

4. Чтение из Excel файла


if object_id('dbo.SomeTable','u') is not null 
  drop table dbo.SomeTable
select 
  *
into 
 SomeTable
FROM 
 OPENDATASOURCE('Microsoft.ACE.OLEDB.12.0','Data Source=c:\xls\Northwind.xlsx;Extended Properties=Excel 8.0')...Products$ s

5. Выборка из DBF. БД DBF должна быть предварительно прилинкована


select 
    *
FROM 
  DBF...Products

6. Курсор


use Northwind
go

declare @CategoryID int

DECLARE MY_CURSOR Cursor  
FOR
select 
 CategoryID
from 
 dbo.Products (nolock) 

open MY_CURSOR 

Fetch NEXT FROM MY_CURSOR INTO 
	@CategoryID 
WHILE @@FETCH_STATUS = 0
BEGIN

  begin try
    ...
      
    if /*условие*/
    begin
      declare @error nvarchar (max) = '...'
      raiserror(@error, 16, 1) -- уровень 16 значит сразу в catch переходит
    end

  end	try
  begin catch			
    print '************Ошибка! ' + ERROR_MESSAGE() ;
  end catch	 
  
  FETCH NEXT FROM MY_CURSOR INTO 
		  @CategoryID 
END
CLOSE MY_CURSOR
DEALLOCATE MY_CURSOR

У 100 Мбит сетевого кабеля, как известно, задействованы не все восемь жил, а только четыре. Отсюда следуют два интересных момента:

1. Если повредится одна из жил, то ее можно заменить одной из оставшихся четырех. И так пока не повредятся пять жил. На картинке красным цветом помечены сигнальные жилы.

350px-RJ-45_TIA-568B_Left

Остальными четырьмя можно подменять вышедшие из строя БО, О, БЗ и З.

2. Через один провод можно подключить два компьютера. Далее я сделал несколько скриншотов с копирайтами автора

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

1

Затем воткнуть эту гидру одним концом в розетку, в двумя другими —  в сетевые карты компьютеров. А на другом конце точно также развернуть через патч-панель.

3

Немного о vSphere

Posted: Март 11, 2013 in vSphere
Метки:, , ,

Взято из vSphere WTFAQ!

vSphere — это общее название всей платформы виртуализации от VMware.
Технологическая основа этой платформы — гипервизор ESX (или ESXi, часто пишут ESX(i), подразумевая одно и ESX, и ESXi, которые несут одни и те же функции), он же — просто гипервизор, или еще встречается название — vSphere ESX.
Гипервизор занимается только тем, что включает/выключает виртуальные машины (ВМ), да управляет ресурсами физического сервера для этих ВМ (выделяет области оперативной памяти и процессорное время).

Есть еще vSphere vCenter — программа (часто называют программу сервером) для управления группой гипервизоров. Она ставится на Windows, объединяет ESX-ы в так называемые кластеры, и творит основные чудеса виртуализации: мигрирует машины без остановки; объединяет серверы ESX в кластера, чтобы те могли запускать ВМ, если один из гипервизоров вдруг перестанет работать; и т.п.
Все подобные чудеса, надо сказать, доступны при наличии:

  1. дисков, доступных всем гипервизорам в кластере (например, отдельное устройство с дисками — система хранения данных)
  2. более одного гипервизора, которые будут с помощью vSphere vCenter объединены в кластер
  3. лицензии. От типа лицензии будут доступны различные наборы «чудес»

vSphere vClient — программа для работы с гипервизорами vSphere ESX или vSphere vCenter. С помощью этой программы делают различные настройки систем виртуализации, и производят действия (например, создают ВМ).

Эту программу обычно ставят на персональные компьютеры системных администраторов.
Фактически — это основное окно, через которую можно «посмотреть» на виртуальную инфраструктуру VMware.

Итак, подытожу:
vSphere — это общее название платформы виртуализации компании VMware, состоящей из:

  • обязательно — гипервизора ESX(i)
  • желательно — vCenter
  • и vClient для администрирования.

все остальное — дополнения и расширения.

От себя добавлю, что можно поставить бесплатный OpenFiler. Он даст интерфейс iSCSI для общего доступа к системе хранения данных.