Wait
Photokaravan.com
 
RSSМы в TwitterМы на FacebookМы на ВКонтакте
Вход на сайт
Имя:
Пароль:
 Запомнить меня
 
Облако тегов
Калибровать монитор

Arduino, PC, Camera.

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

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

  Шаг первый - ИК пульт.

 Вы случайно под новый год не решили поменять телевизор или выбросить старый DVD проигрыватель. Если нет, то жаль, так бы вам очень пригодился дистанционный пульт. У меня таких накопилось штук восемь. Но это не все, чем полезна старая электроника. Вооружившись отверткой можно вытащить ИК приемник.  Приемник обычно размещаются под передней крышкой прибора.
   
Подойдет любой IR приемник TSOP17, TSOP13, SM3374, TK19 и им подобные. После того, как приемник найден, собираем маленькую схему на Arduino и приступаем к изучению пульта управления.  
Пульт желательно использовать не самый новый, но и не самый старый, чтоб было максимум рабочих кодов. Для сканирования нужно загрузить библиотеку IRremote. Создать Sketch для Arduino IR_code_to_232.pde
#include <IRremote.h>

int RECV_PIN = 2;
int STATUS_PIN = 13;

IRrecv irrecv(RECV_PIN);
decode_results results;

void setup()
{
Serial.begin(115200);
irrecv.enableIRIn(); // Start the receiver
}

int codeType = -1; // The type of code

void loop() {
if (irrecv.decode(&results)) {
codeType = results.decode_type;
if (codeType != UNKNOWN) {
if (results.value != REPEAT) {
Serial.println(results.value, HEX);
}
}
irrecv.resume();  
}
}
и загрузить код в Arduino. Открыть терминал и, нажимая кнопки на пульте управления, записать код для каждой кнопки. Для ленивых как я. :) открываем командное окно  
Start > «cmd», перейти в рабочую директорию, туда же скопировать программу RS232read.7z  
> RS232read.exe 7 115200 > rs232.txt.
 Где 7 - номер COM порта, 115200 - скорость, rs232.txt файл куда сохраняются принимаемые данные. После этого открыть rs232.txt и скопировать коды в Sketch  должно получиться вот так.
#define button1 0xFF906F
#define button2 0xFFB847
#define button3 0xFFF807
#define button4 0xFFB04F
#define button5 0xFF9867
#define button6 0xFFD827
#define button7 0xFF8877
#define button8 0xFFA857
#define button9 0xFFE817
Теперь можно запрограммировать кнопку «1» на спуск камеры. IR_Shutter.pde
#include <IRremote.h>

#define button1 0xFF906F
#define button2 0xFFB847
#define button3 0xFFF807
#define button4 0xFFB04F
#define button5 0xFF9867
#define button6 0xFFD827
#define button7 0xFF8877
#define button8 0xFFA857
#define button9 0xFFE817

const int Shot  = 11;
const int Focus  = 12;

int RECV_PIN = 2;
int STATUS_PIN = 13;

IRrecv irrecv(RECV_PIN);
decode_results results;

void setup()
{
Serial.begin(115200);
irrecv.enableIRIn(); // Start the receiver
pinMode(STATUS_PIN, OUTPUT);
pinMode(Shot, OUTPUT);
pinMode(Focus, OUTPUT); 
}

int codeType = -1; // The type of code

void loop() {
digitalWrite(STATUS_PIN, LOW );
if (irrecv.decode(&results)) {
codeType = results.decode_type;
if (codeType != UNKNOWN) {
if (results.value != REPEAT) {
if (results.value == button1) {
digitalWrite(Focus, HIGH);
digitalWrite(Shot, HIGH);
delay(1000);                  // waits for a second
digitalWrite(Focus, LOW);
digitalWrite(Shot, LOW); 
}
if (results.value == button2) {
Serial.println("Button 2");
}
if (results.value == button3) {
Serial.println("Button 3");
}
if (results.value == button4) {
Serial.println("Button 4");
}
if (results.value == button5) {
Serial.println("Button 5");
}
if (results.value == button6) {
Serial.println("Button 6");
}
if (results.value == button7) {
Serial.println("Button 7");
}
if (results.value == button8) {
Serial.println("Button 8");
}
if (results.value == button9) {
Serial.println("Shutter");
}
//Serial.println(results.value, HEX);
//irrecv.resume(); // Receive the next value
}
}
digitalWrite(STATUS_PIN, HIGH);  
irrecv.resume();  
}
}
Шаг второй - Windows Image Acquisition (WIA).  

Почему WIA? Потому что позволяет управлять камерой, не углубляясь в  Nikon SKD или Canon SDK. Свободно распространяется Microsoft, управлять можно из VBScript. Чтобы лучше понять, что может WIA, запустите пару скриптов из командной строки.
' before!!!! run cmd as Administrator and "cscript.exe //H:cscript" 
<job>
<reference object="wia.DeviceManager" />
<object id="DevMan" progid="Wia.DeviceManager" />
<object id="dlg" progid="WIA.CommonDialog" />
<script language="VBScript">

' Copyright 2011 All Rights Reserved
' Use and distribution for non-commercial purposes permitted
' http://karu2003.blogspot.com/
Option Explicit

Dim WiaDev 'As wia.Device
Dim WiaItm 'As wia.Item

Dim dev 'As Device
Dim i 'As Integer
Dim s 'As String
Dim p 'As Property

Set dev = dlg.ShowSelectDevice

For Each p In dev.Properties
s = p.Name '& "(" & p.PropertyID & ")"
'MsgBox s
WScript.echo s
Next

</script>
</job>
получим список всех Properties (свойства) камеры.
' before!!!! run cmd as Administrator and "cscript.exe //H:cscript" 
<job>
<reference object="wia.DeviceManager" />
<object id="DevMan" progid="Wia.DeviceManager" />
<object id="dlg" progid="WIA.CommonDialog" />
<script language="VBScript">

' Copyright 2011 All Rights Reserved
' Use and distribution for non-commercial purposes permitted
' http://karu2003.blogspot.com/

Option Explicit

Dim WiaDev 'As wia.Device
Dim WiaItm 'As wia.Item

Dim dev 'As Device
Dim p 'As Property
Dim s 'As String
Dim i 'As Integer

Set dev = dlg.ShowSelectDevice

For Each p In dev.Properties
s = p.Name & "(" & p.PropertyID & ") = "
If p.IsVector Then
s = s & "[vector of data]"
Else
s = s & p.Value
If p.SubType <> UnspecifiedSubType Then       
If p.Value <> p.SubTypeDefault Then
s = s & "(Default = " & p.SubTypeDefault & ")"
End If
End If
End If

If p.IsReadOnly then
s= s & " [READ ONLY]"
else
Select Case p.SubType
Case FlagSubType
s = s & " [ valid flags include:"
For i = 1 To p.SubTypeValues.Count
s = s & p.SubTypeValues(i)
If i <> p.SubTypeValues.Count Then
s = s & ", "
End If
Next
s = s & " ]"
Case ListSubType
s = s & " [ valid values include:"
For i = 1 To p.SubTypeValues.Count
s = s & p.SubTypeValues(i)
If i <> p.SubTypeValues.Count Then
s = s & ", "
End If
Next
s = s & " ]"
Case RangeSubType
s = s & " [ valid values in the range from " & _
p.SubTypeMin & " to " & p.SubTypeMax & _
" in increments of " & p.SubTypeStep & " ]"
Case Else 'UnspecifiedSubType
End Select
End If

'MsgBox s
WScript.echo s
Next

</script>
</job>
получим список всех Properties и все возможные value (значение). Обратите внимание на два свойства "F Number" - диафрагма и "Exposure Time" — выдержка, значения этих свойств отличаются от привычных фотографу. Чтобы установить выдержку в 1 секунду нужно отправить в камеру значение 10000, для диафрагмы F8 нужно отправить значение 800. Диафрагму нужно умножить на 100. С выдержкой искомое значение получается несколько сложнее. Чтобы установить выдержку 1/160 нужно 10000/160 и отбросить дробную часть. Получим 62. 
(1,"6400");
(2,"4000");
(3,"3200");
(4,"2500");
(5,"2000");
(6,"1600");
(8,"1250");
(10,"1000");
(12,"800");
(13,"750");
(15,"640");
(20,"500");
(25,"400");
(28,"350");
(31,"320");
(40,"250");
(50,"200");
(55,"180");
(62,"160");
(80,"125");
(100,"100");
(111,"90");
(125,"80");
(166,"60");
(200,"50");
(222,"45");
(250,"40");
(333,"30");
(400,"25");
(500,"20");
(666,"15");
(769,"13");
(1000,"10");
(1250,"8");
(1666,"6");
(2000,"5");
(2500,"4");
(3333,"3");
(4000,"2.5");
(5000,"2");
(6250,"1.6");
(6666,"1.5");
(7692,"1.3");
(10000,"1\"");
(13000,"1.3\"");
(15000,"1.5\"");
(16000,"1.6\"");
(20000,"2\"");
(25000,"2.5\"");
(30000,"3\"");
(40000,"4\"");
(50000,"5\"");
(60000,"6\"");
(80000,"8\"");
(100000,"10\"");
(130000,"13\"");
(150000,"15\"");
(200000,"20\"");
(250000,"25\"");
(300000,"30\"");
Для примера из командной строки запустите скрипт 160f8.wsf
' before!!!! run cmd as Administrator and "cscript.exe //H:cscript" 
<job>
<reference object="wia.DeviceManager" />
<object id="DevMan" progid="Wia.DeviceManager" />
<object id="dlg" progid="WIA.CommonDialog" />
<script language="VBScript">

' Copyright 2011 All Rights Reserved
' Use and distribution for non-commercial purposes permitted
' http://karu2003.blogspot.com/

Option Explicit

Dim WiaDev 'As wia.Device

Set WiaDev = dlg.ShowSelectDevice
WiaDev.properties("Exposure Time").value = 62 
WiaDev.properties("F Number").value = 800 

</script>
</job>
и камера поменяет экспозицию на 1/160 F8. Очень важный момент: количество свойств и их значения могут меняться от камеры к камере и они могут быть только для чтения. Так что, перед тем, как изменять какие-либо свойства, убедитесь, что они доступны для записи.

Шаг три — Arduino > WIA > Camera.  

Первым делом организуем срабатывание затвора по пути Arduino > PC > Camera. Для этого загрузим Sketch IR_Shutter.pde где на код кнопки «1» камера срабатывать на прямую от Arduino, а на код кнопки «9» Arduino будет отсылать в компьютер «Shutter». Со стороны компьютера из командной строки запустим скрипт  Shutter.wsf
' before!!!! run cmd as Administrator and "cscript.exe //H:cscript" 
<job>
<reference object="wia.DeviceManager" />
<object id="DevMan" progid="Wia.DeviceManager" />
<object id="dlg" progid="WIA.CommonDialog" />
<script language="VBScript">

' Copyright 2011 All Rights Reserved
' Use and distribution for non-commercial purposes permitted
' http://karu2003.blogspot.com/

Option Explicit

Dim WiaDev 'As wia.Device
Const ForReading = 1
dim fso
dim com
dim s
Dim strPortName' As String

strPortName = GetComPort

Set fso = CreateObject("Scripting.FileSystemObject")
Set com = fso.OpenTextFile(strPortName & ":115200,N,8,1", ForReading)

Set WiaDev = dlg.ShowSelectDevice

WScript.echo "Shutter Camera Control with Arduino Script 1.0 "
WScript.echo "Copyright 2011 All Rights Reserved"
WScript.echo "Use and distribution for non-commercial purposes permitted"
WScript.echo "http://karu2003.blogspot.com/"
Wscript.echo "Controlling  " & WiaDev.Properties("Description").Value

' set raw
WiaDev.Properties("Format").Value = "{B96B3CA9-0728-11D3-9D7B-0000F81EF32E}"
Wscript.echo "Shooting in RAW Format"
' set jpg
'WiaDev.Properties("Format").Value = "{B96B3CAE-0728-11D3-9D7B-0000F81EF32E}"
'Wscript.echo "Shooting in JPG Format"

WScript.echo "Start to read data from " & strPortName
WScript.echo "Press Ctrl-Break to exit"

Do While 1 
Do While com.AtEndOfStream <> True
WScript.Sleep(100)
s = com.ReadLine
'WScript.echo (s)
If s = "Shutter" Then
WiaDev.ExecuteCommand (wiaCommandTakePicture)
WScript.echo (s)
End If
Loop
Loop

com.Close()

'************************************************************************
Function GetComPort()
Dim strComputer
Dim objWMIService
Dim colItems
Dim objItem
Dim objRgx 'As RegExp
Dim objRegMatches 'As MatchCollection
Dim strDevName

GetComPort = ""

strComputer = "."
Set objWMIService = GetObject( _
"winmgmts:\\" & strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery _
("Select * from Win32_PnPEntity")
For Each objItem In colItems
If ("FTSER2K" = objItem.Service) And ("FTDI" = objItem.Manufacturer) Then

set objRgx = CreateObject("vbScript.RegExp")

strDevName = objItem.Name
objRgx.Pattern = "COM[0-9]+"
Set objRegMatches = objRgx.Execute(strDevName)
If objRegMatches.Count = 1 Then
GetComPort = objRegMatches.Item(0).Value
Else
End If
End If
Next
End Function
' ********************************************************************

</script>
</job>
Теперь у нас есть две возможности электорального спуска затвора и все с одного пульта управления. Немного изменив код, можно добавить сохранение снятого кадра прямо на компьютер. Но об этом в другой раз. Информацию, как это сделать, можно найти на DIYPhotoBits.com. Теперь осталось изменить пару строчек исходного кода в скрипте и Arduino и получится универсальный командный пульт. Но перед этим стоит разобраться, какие свойства камеры можно изменять. Для своих фото экспериментов - макро, HDRi, предметки мне хватает шести основных:

 ("White Balance").value
("F Number").value
("Exposure Time").value
("Exposure Mode").value
("Exposure Index").value
("Exposure Compensation").value

' before!!!! run cmd as Administrator and "cscript.exe //H:cscript" 
<job>
<reference object="wia.DeviceManager" />
<object id="DevMan" progid="Wia.DeviceManager" />
<object id="dlg" progid="WIA.CommonDialog" />
<script language="VBScript">

' Copyright 2011 All Rights Reserved
' Use and distribution for non-commercial purposes permitted
' http://karu2003.blogspot.com/

Option Explicit

Dim WiaDev 'As wia.Device
Const ForReading = 1
dim fso
dim com
dim s
Dim strPortName' As String
Dim k

strPortName = GetComPort

Set fso = CreateObject("Scripting.FileSystemObject")
Set com = fso.OpenTextFile(strPortName & ":115200,N,8,1", ForReading)

Set WiaDev = dlg.ShowSelectDevice

WScript.echo "Shutter Camera Control with Arduino Script 1.0 "
WScript.echo "Copyright 2011 All Rights Reserved"
WScript.echo "Use and distribution for non-commercial purposes permitted"
WScript.echo "http://karu2003.blogspot.com/"
Wscript.echo "Controlling  " & WiaDev.Properties("Description").Value

' set raw
WiaDev.Properties("Format").Value = "{B96B3CA9-0728-11D3-9D7B-0000F81EF32E}"
Wscript.echo "Shooting in RAW Format"
' set jpg
'WiaDev.Properties("Format").Value = "{B96B3CAE-0728-11D3-9D7B-0000F81EF32E}"
'Wscript.echo "Shooting in JPG Format"

WScript.echo "Start to read data from " & strPortName
WScript.echo "Press Ctrl-Break to exit"

Do While 1 
Do While com.AtEndOfStream <> True
s = com.ReadLine
k = Len(s)
'WScript.echo (s)
If  s = "Shutter" Then
WiaDev.ExecuteCommand (wiaCommandTakePicture)
WScript.echo (s)
End If

If Left(s,2) = "WB" Then
WiaDev.properties("White Balance").value = CDbl(Mid(s,3,k-2))
End If

If Left(s,2) = "FN" Then
WiaDev.properties("F Number").value =  CDbl(Mid(s,3,k-2))
End If

If Left(s,2) = "ET" Then
WiaDev.properties("Exposure Time").value = CDbl(Mid(s,3,k-2))
End If

If Left(s,2) = "EM" Then
WiaDev.properties("Exposure Mode").value = CDbl(Mid(s,3,k-2))
End If

If Left(s,2) = "EI" Then
WiaDev.properties("Exposure Index").value = CDbl(Mid(s,3,k-2))
End If

If Left(s,2) = "EC" Then
WiaDev.properties("Exposure Compensation").value = CDbl(Mid(s,3,k-2))
End If    

WScript.Sleep(100)
Loop
Loop

com.Close()

'************************************************************************
Function GetComPort()
Dim strComputer
Dim objWMIService
Dim colItems
Dim objItem
Dim objRgx 'As RegExp
Dim objRegMatches 'As MatchCollection
Dim strDevName


GetComPort = ""

strComputer = "."
Set objWMIService = GetObject( _
"winmgmts:\\" & strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery _
("Select * from Win32_PnPEntity")
For Each objItem In colItems
If ("FTSER2K" = objItem.Service) And ("FTDI" = objItem.Manufacturer) Then

set objRgx = CreateObject("vbScript.RegExp")

strDevName = objItem.Name
objRgx.Pattern = "COM[0-9]+"
Set objRegMatches = objRgx.Execute(strDevName)
If objRegMatches.Count = 1 Then
GetComPort = objRegMatches.Item(0).Value
Else
End If
End If
Next
End Function
' ********************************************************************
</script>
</job>
IR_WIAComander.pde
#include <IRremote.h>
//WIA Format
//("White Balance").value =
//("F Number").value = 
//("Exposure Time").value =
//("Exposure Mode").value =
//("Exposure Index").value =
//("Exposure Compensation").value =

const char* WB = "WB"; //"White Balance";
const char* FN = "FN"; //"F Number";
const char* ET = "ET"; //"Exposure Time";
const char* EM = "EM"; //"Exposure Mode";
const char* EI = "EI"; //"Exposure Index";
const char* EC = "EC"; //"Exposure Compensation";

#define button1 0xFF906F
#define button2 0xFFB847
#define button3 0xFFF807
#define button4 0xFFB04F
#define button5 0xFF9867
#define button6 0xFFD827
#define button7 0xFF8877
#define button8 0xFFA857
#define button9 0xFFE817

const int Shot  = 11;
const int Focus  = 12;

int RECV_PIN = 2;
int STATUS_PIN = 13;
String sProperties;

IRrecv irrecv(RECV_PIN);
decode_results results;

void setup()
{
Serial.begin(115200);
irrecv.enableIRIn(); // Start the receiver
pinMode(STATUS_PIN, OUTPUT);
pinMode(Shot, OUTPUT);
pinMode(Focus, OUTPUT); 
}

int codeType = -1; // The type of code

void loop() {
digitalWrite(STATUS_PIN, LOW );
if (irrecv.decode(&results)) {
codeType = results.decode_type;
if (codeType != UNKNOWN) {
if (results.value != REPEAT) {
if (results.value == button1) {
digitalWrite(Focus, HIGH);
digitalWrite(Shot, HIGH);
delay(1000);                  // waits for a second
digitalWrite(Focus, LOW);
digitalWrite(Shot, LOW); 
}
if (results.value == button2) {
sProperties = FN;
sProperties = sProperties + "800";
Serial.println(sProperties);
delay(100);
sProperties = ET;
sProperties = sProperties + "62";
Serial.println(sProperties);

}
if (results.value == button3) {
sProperties = FN;
sProperties = sProperties + "400";
Serial.println(sProperties);
delay(100);
sProperties = ET;
sProperties = sProperties + "166";
Serial.println(sProperties);
}
if (results.value == button4) {
Serial.println("Button 4");
}
if (results.value == button5) {
Serial.println("Button 5");
}
if (results.value == button6) {
Serial.println("Button 6");
}
if (results.value == button7) {
Serial.println("Button 7");
}
if (results.value == button8) {
Serial.println("Button 8");
}
if (results.value == button9) {
Serial.println("Shutter");
}
//Serial.println(results.value, HEX);
//irrecv.resume(); // Receive the next value
}
}
digitalWrite(STATUS_PIN, HIGH);  
irrecv.resume();  
}
}
Вот и все, что нужно. Дальше каждый расширяет код под Arduino под свои потребности. Чтобы не работать постоянно, из командной строки написал программу  IR_WIAComander.7z . По логике работы программа ничем не отличается от скрипта , добавлено несколько проверок на подключение камеры и Arduino.
Но, чтобы программа работала, в системе нужно зарегистрировать библиотеку работы с  COM Port.

 1. загрузить MSCOMM32.ocx  
2. copy MSCOMM32.ocx в C:\Windows\System32\  
3. открыть cmd как администратор
 4. > regsvr32 C:\Windows\System32\MSCOMM32.ocx
 5. загрузить vbctrls.zip
 6. добавить лицензию в регистер.
Надеюсь, что описал не очень запутано.
 Удачи в эксперементах.

© Andrew Buckin.

TODO:  
Multiple FTDI Chip.
Detect Arduino Bootloader
 Send Properties to Arduino.
Теги:

Комментарии

Ollivander
03.01.2012 2:56
Спасибо, интересная статья.

Полагаю, многим читателям помогут сориентироваться в материале вот эти две ссылки (вторая совершенно не уникальна и дана просто для ознакомления):

http://ru.wikipedia.org/wiki/Arduino

http://www.amazon.com/Arduino-Nano-v3-0/dp/B003YVL34O
tim001
03.01.2012 4:24
Спасибо, познавательно. Паяльник в руках держу, с программированием проблемы))))
А возможно вместо ИК управления, сделать управление по Wi-Fi?(родное решение стоит вовсе не гуманно) мне просто нужно достаточно удалённое управление фотокамерой для будущего проекта.
DwMan
03.01.2012 7:16
что-нибудь вертолётное? :)
ka_ru
03.01.2012 7:46
Можно и радио подключит.
Пара радио-модулей есть в тумбочке. Сейчас модули стоят не дорого 5-10€.
Если на выходных время будет расскажу как. Только надо подумать как сделать все мобильное и не много паять.
tim001
03.01.2012 9:30
DwMan, почти угадали, аппарат будет летательный(в проекте, но уже не вертолёт)
А возможно найти радиомодуль с дальностью метров 300? чтобы была возможность менять экспозицию на камере с ноутбука. Я видел у одного кажется австралийца в блоге управление камерой по Wi-Fi, но дальность смешная.
ka_ru
03.01.2012 9:53, изменен 03.01.2012 10:09
Все зависит от частоты и антенны.
300 метров прямой видимости может любой. Я бы посоветовал 433Мгц.
WiFi будет много потреблять. Я пробовал по WiFi на воде, лодка, два километра с метровой антенной на берегу и 7 дБ антенна на лодке.
Если для самолета или вертолета. Я бы посмотрел систему на ангстреме, плата потребляют до 2Вт есть библиотеки gPhoto2 и радио модем на 433МГц до 100мВт. Но можно WiFi но модули потребляют до 1Вт.
tim001
03.01.2012 10:09, изменен 03.01.2012 10:10
Летательный аппарат будет управляться по радио(2,4) Макс высота метров 500( скорее от 100 до 250) С учётом полётного времени минут 10, то потребление не особо смущает Li-Po батареи можно заряжать большими токами, да и стоимость батарей на сегодня-доступная, главное вес девайса.
Если Вы можете подсказать гоовое решение или около того будет замечательно, но в принципе готов в разумных пределах платить за рабочее решение-управление камерой с земли(всмысле какие устройства нужны и программа под ардуино.
ka_ru
03.01.2012 21:25
О цене лучше в личку.
Реальных вариантом может быть два. Очень маленький контроллер и embedded Linux.
Вариант с Linux у меня работает. Управлять можно через радио(433М) и WiFi(2.4Г).
Если использовать для летательного аппарата нужно оптимизировать вес и потребление.
У Linux очень большое достоинство не надо разбираться с PTP протоколом, минус - цена и время загрузки системы. У маленького контроллер вес маленький, габариты маленькие, но может понадобиться адаптация программ под производителя камеры. Последний вариант у меня в разработке и пока не готов для публикации.

Мои популярные записи

Блог ka_ru
ka_ru - 09.04.2012 17:08

Другие популярные записи

  Калибровать монитор
2012 © Photokaravan.com
Все права защищены
Главная | Галерея | Конкурсы | Блоги | Форум