Monday, May 16, 2016

Using Hall sensors for position feedback

Brushless DC (BLDC) motors implement Hall sensors for commutation. These hall sensors produce voltage output according to rotor position [1]. Their combined outputs are used by motor drivers to sense rotor angular position and send current to the correct motor winding to obtain continuous rotation.

In one of our projects we had a BLDC motor with integrated encoder for position feedback. I happened to choose a mating connector for the encoder that has no mechanical polarization. So the connector could be attached both ways. On one careless day, which was just several days before the final project meeting and prototype demonstration, I reverse connected the connector and the encoder burned due to reverse supply voltage polarization. We contacted the motor supplier but the lead time for a new one was 6 weeks. We ordered one anyway but we had to either try to postpone the meeting or come up with a solution. Then it came to my mind that we could use the hall sensors for position feedback. The output would be very very coarse compared to the encoder, 60° resolution versus 0.35°, but luckily in this specific project we had a high gear ratio between the motor and the system to be position controlled. When divided by the gear ratio, which was around 440, you get a resolution of 60°/440=0.14° degree on output shaft which is not bad at all. At least it might save the day.

So how do you convert Hall sensor readings to motor angular position? Reading the output of three Hall sensors using an analog input card while rotating the motor shaft by hand produces the result given in Figure 1. The figure is for clockwise shaft rotation. Note that revolution per second (RPS) of motor shaft must be less than sampling frequency (fs) divided by 6 (because at every 60 degrees a Hall sensor changes state, meaning in one full turn there are 6 state changes). Otherwise the motor turns so fast that between your two consecutive sampling points you miss a Hall sensor voltage change and corrupt your sequence. 


Figure 1. Hall sensor readings for clockwise rotation

As the shaft is being rotated, the sensor outputs switch between high and low states, following a specific sequence. In order to determine the sequence, we need to follow the rising and falling edges of the signals. But before that, it would be better to convert analog signal to a discrete boolean signal and get rid of noise. Let us assume the analog voltage readings are named h1, h2 and h3 respectively. Then by defining an error margin, we get rid of the noise (Figure 2).

h_anlg = [h1;h2;h3]; % raw analog voltage signal
h_quan = h_anlg; % quantized signal
marg = 1; % a noise margin of +/- 1 volts
h_quan(abs(h_quan-5)<marg) = 5; % set all values in +/- marg vicinity of 5 volts to 5 volts
h_quan(abs(h_quan-0)<marg) = 0; % set all values in +/- marg vicinity of 0 volts to 0 volts

Figure 2. Analog Hall output is quantized to remove noise

The next step is to scale the signals between 0 and 1 by taking its sign.

h_bool = h_quan;
h_bool = sign(h_bool); % scale signal between 0 and 1.

Now we can locate rising and falling edges and determine states of each sensor for a full rotation. Let us find first the indices where signals change state.

h_bool_d = diff(h_bool,1,2);
[I,J] = find(abs(h_bool_d)>0,5);

In the code snippet above, I is the index for hall sensor and J is the index for time at which change starts. Note that the change starts at index J and new state is reached at index J+1. Now let us initialize our state vector and fill it. We know that there are 6 different states in one turn and after one turn the sequence repeats itself. Also the first state is the state at time t=0. So

states = zeros(3,6);
states(:,1) = h_bool(:,1); % first state is the state at t=0
states(:,2:6) = h_bool(:,J+1); % others are the signal levels just after an edge

For my case the states variable is obtained as follows.

states =

     0     0     0     1     1     1
     0     1     1     1     0     0
     1     1     0     0     0     1

You can reach the same conclusion by looking at Figure 1 directly. In Figure 1, the starting state is 0, 0, 1. Out of the three signals, first the red one changes state and the next state is 0, 1, 1 etc. But the code automates the process.

Now that we obtained the sequence we can create a Simulink model and convert these signals to motor angle. We first need to determine which state we are in at start-up, then at each sample time, check our new state. If the new state is to the right of the previous state in our sequence table, the motor turned clockwise 60 degrees (note that we collected the data and generated the sequence for a clockwise rotation). If the new state is to the left of the previous state in our sequence table, the motor turned counter-clockwise 60 degrees. If the new state jumped more than one state compared to previous state, then the motor turned too fast with respect to our sampling frequency and we missed an unknown amount of state changes. In this case we get an error that builds-up in our motor angle conversion. We either accept this error or throw a warning/exception. In Figure 3, a sample Simulink model is shown. You can use a Stateflow block to implement the algorithm defined in this paragraph or you can write a Matlab function as I did.


Figure 3. Sample Simulink model that converts simulated hall sensor outputs to motor angular position

The MATLAB Function block has two inputs v and u. v is the 3x6 states matrix obtained above. u is a 1x5 vector whose first three elements are boolean hall sensor signals h (take care of the ordering), the fourth element is a scalar s that shows current state, and the last element is a counter c for determining motor angle. The output of the block are scalars s and c which are fed back to the block as input to be used for the next sampling time. The blocks inside yellow region simulate the BLDC motor sensor outputs. Slider Gain block can be adjusted between +/- 720 degrees and is used to simulate motor shaft rotation. In the actual application the blocks inside the yellow region should be replaced by the analog input card. The Quantizer and Sign blocks just before the MATLAB Function block convert noisy analog signals to boolean signals. The counter output c of MATLAB Function block is multiplied by 60 to convert the counter to motor angular position in degrees. The code inside MATLAB Function block is as follows.

function y = fcn(v, u)
h=u(1:3); % boolean hall sensor signals
s=u(4); % switch indicating current state
c=u(5); % counter
sta = v'; % copy states matrix
if (s==0) % initially s==0
    c = 0;
    if (all(h==sta(1,:)))
        s = 1; 
    elseif (all(h==sta(2,:)))
        s = 2;
    elseif (all(h==sta(3,:)))
        s = 3;
    elseif (all(h==sta(4,:)))
        s = 4;
    elseif (all(h==sta(5,:)))
        s = 5;
    elseif (all(h==sta(6,:)))
        s = 6;
    end
else
    nxt = mod(s,6)+1; % next state column index
    pre = mod(s-2,6)+1; % previous state column index
    if (all(h==sta(nxt,:))) % current state is to the right of prev state
        s = nxt;
        c = c+1;
    elseif (all(h==sta(pre,:))) % current state is to the left of prev state
        s = pre;
        c = c-1;
    else
% you missed a state change. raise warning/error or do nothing.
    end
end
y=[s,c];

Using the code above, we were able to sufficiently control our prototype (of course we had to implement some other algorithms such as dead zones to prevent chattering and limit cycles etc.). We were able to postpone the final meeting and demonstration to a much later time but it did us no good because to this day we still couldn't receive the replacement motors yet. We demonstrated the project explaining the situation and our project was approved. The moral of the story is that think ahead and always buy spares because accidents and mistakes happen.

REFERENCES:
[1] http://www.parkermotion.com/manuals/OEM770T/5_Hall_Effects_770T.pdf

Friday, January 15, 2016

The things you can do with Matlab

I have been asked this question a couple of times by new engineers: "What do you use Matlab for? What can you accomplish with it? Where do you use it?". My general answer to this question is that "Matlab is a high level language with lots of built-in functions and its magic is the built-in functions. Using those functions, you can do many complex calculations/tasks with minimal coding effort." Then I give examples of the projects I use Matlab for and one of them is a very strange analysis considering that I am a mechanical engineer. Recently a past colleague of mine brought the project to my attention and I was filled with nostalgia and scanned through old archives to find the codes. I ran the code and to my surprise it worked without giving any errors. So here goes the story behind it.

Once upon a time, I was the team leader for a project and at the time our only optical engineer was doing his military service. We had to design a lens which would satisfy some optical requirements. The lens would collect incident radiation from a scene and focus it on a detector. A requirement was to deliberately introduce a defocus on detector so that a circular area is illuminated on detector surface instead of a point. And there was the problem of optimizing several parameters such as energy density inside the illuminated area, change of this energy with respect to angle of incidence of coming rays, diameter of the circle, radiometric calculations, detection range etc.

Usually optical engineers design optical systems using a software called Zemax but I did not have any knowledge, and still don't, on how to use the software. So I told to myself, "I have good old Matlab, and Snell's Law, so lets see what I can do." Snell's Law tells us how a light ray behaves when it passes through a boundary of two media with different indices of refraction. I approached the problem as a two dimensional problem since it is always better to start with a simplified problem. I defined all the boundaries of the lens as symbolic expressions in Matlab. The symbolic expressions allowed me to represent the front and back surfaces of the lens as concave, convex or planar. So I had some design requirements that I had to satisfy, and parameters of the lens (front and back surface shape/radius, diameter and thickness of lens) and distance between detector and lens were to be determined. So I used a brute force technique to find some starting results. I used cascaded 'for' loops, changing each parameter by some amount on each pass, and looked if the requirements were satisfied. After lots of trials, the code evolved to give satisfactory results and it was time to run the analysis for a larger span of parameters. I left the computer running on weekend, hoping the code would not give any errors, and on Monday when I went to work the code was finished and I had a txt file with a bunch of possible candidate lens designs. The list had more than 200 entries but this thorough analysis gave me an idea on where I should look for a solution. Limiting the span of parameters to smaller ranges and focusing on these candidate solution region gave better results in less time.

Below is a snapshot from the Matlab graphical user interface that I made. One can see the parameters that define the lens surfaces on the left, a figure showing the result of ray tracing equations in the middle and the defocused circular area on detector on the right. 


After designing the lens, I chose a commercial off-the-shelf lens with similar dimensions and we were ready to continue with the design. We even assembled a prototype with the designed lens and it worked in laboratory tests. I left the project at this stage and I don't know if they are still using the same lens or not (probably not). But it was a nice challenge and code practice for me and gave us valuable results in the end. I expanded the code and gui so much afterwards that it was able to do radiometric calculations according to results of ray tracing, optimize the detector and lens parameters if required, and report the results as graphics and/or animated gifs. I still have plans to extend the underlying equations for a general 3 dimensional problem. I should have some papers in those folders for 3 dimensional representation of Snell's Law. But I am still waiting for the right time to go into those.

For me this was one of those strange things you use Matlab for.







Wednesday, September 9, 2015

Transforming and plotting coordinate systems in MATLAB

I have just started a new project which involves lots of coordinate transformations. So I created my basic functions which would let me define, translate, rotate, plot coordinate systems. Here is the code snippet:

function MessingWithCoordinateSystems
clear all;clc; close all;

% Define absolute coordinate system (ABS).
csys_ABS = create_csys_object([0;0;0], eye(3));

% Define a new csys by rotating ABS around y axis 90 degrees, and then
% rotating around x axis by 45 degrees, then translating by 5 units in x
% direction.
Rot_ABS_to_NewCSYS = eulseq('21',[90,45]); %Rotation matrix that will rotate WCS to new csys
csys_New = rotate_csys(csys_ABS, Rot_ABS_to_NewCSYS); %Rotate WCS to obtain new csys
csys_New = translate_csys(csys_New, csys_New, [0;0;2]); %Translate new csys

% Define vector from ABS origin to NewCSYS origin.
R_ABS_to_NewCSYS_in_ABS = csys_New.Origin-csys_ABS.Origin;

% Plot the results.
h=figure(1);
plot_csys(h,csys_ABS);
plot_csys(h,csys_New);
plot_vector(h,R_ABS_to_NewCSYS_in_ABS,csys_ABS);
end

function OUT = create_csys_object(ORIGIN, ORIENTATION)
% Creates a structure OUT with the following properties:
%  .Origin: 3x1 vector representing origin of coordinate system. Copied
%           from ORIGIN.
%  .Orientation: 3x3 matrix whose columns represent directions of x,y,z
%                axes with respect to absolute frame. Copied from
%                ORIENTATION.

    if(size(ORIGIN) ~= [3,1])
        error('ORIGIN size must 3x1');
    end
    if(size(ORIENTATION) ~= [3,3])
        error('ORIENTATION size must 3x3');
    end

    OUT.Origin = ORIGIN;
    OUT.Orientation = ORIENTATION;
end

function OUT = translate_csys(CSYS, CSYS_BASE, TRANSLATION)
% Translates coordinate system CSYS by the amount given by TRANSLATION
% TRANSLATION vector is resolved in CSYS_BASE.
%
% CSYS is the coordinate frame to be translated. It is a structure with
% following properties:
%  .Origin: 3x1 vector representing origin of coordinate system.
%  .Orientation: 3x3 matrix whose columns represent directions of x,y,z
%                axes with respect to absolute frame
% CSYS_BASE is the coordinate frame that TRANSLATION vector is resolved
% in. It is a structure with following properties:
%  .Origin: 3x1 vector representing origin of coordinate system.
%  .Orientation: 3x3 matrix whose columns represent directions of x,y,z
%                axes with respect to absolute frame
% TRANSLATION is a 3x1 vector containing displacements in x,y,z axes of
% coordinate frame CSYS_BASE.

    OUT.Origin = CSYS.Origin+CSYS_BASE.Orientation*TRANSLATION;
    OUT.Orientation = CSYS.Orientation;
end

function OUT = rotate_csys(CSYS,ROTMAT)
% Rotates a given coordinate system
%
% CSYS is a structure with following properties:
%  .Origin: 3x1 vector representing origin of coordinate system.
%  .Orientation: 3x3 matrix whose columns represent directions of x,y,z
%                axes with respect to absolute frame.
%
% ROTMAT is a 3x3 rotation matrix. 

    OUT.Orientation = CSYS.Orientation*ROTMAT;
    OUT.Origin = CSYS.Origin;
end

function plot_csys(HANDLE, CSYS)
% Plots the coordinate system given by CSYS to figure with handle 
% HANDLE
%
% HANDLE is handle to the figure.
% CSYS is the coordinate system to be drawn. It is a structure with
% following properties:
%  .Origin: 3x1 vector representing origin of coordinate system.
%  .Orientation: 3x3 matrix whose columns represent directions of x,y,z
%                axes.

    figure(HANDLE);
    hold on;
    colors = 'rgb';
    arrowTail = CSYS.Origin; 
    for i=1:3
        arrowHead = CSYS.Origin+CSYS.Orientation(:,i);
        line([arrowTail(1),arrowHead(1)],[arrowTail(2),arrowHead(2)],...
            [arrowTail(3),arrowHead(3)],'Color',colors(i));
    end

    hold off;
    xlabel('X');
    ylabel('Y');
    zlabel('Z');
    grid on;
    axis equal;
end

function plot_vector(HANDLE, VECTOR, CSYS)
% Plots the vector given by VECTOR resolved in coordinate system 
% CSYS to figure with handle HANDLE.
%
% HANDLE is handle to the figure.
% VECTOR is a 3x1 vector.
% CSYS is the coordinate system that the vector is resolved in. It is a
% structure with following properties:
%  .Origin: 3x1 vector representing origin of coordinate system.
%  .Orientation: 3x3 matrix whose columns represent directions of x,y,z
%                axes with respect to absolute coordinate frame.

    figure(HANDLE);
    hold on;
    arrowTail = CSYS.Origin;
    arrowHead = CSYS.Origin+VECTOR;
    line([arrowTail(1),arrowHead(1)],[arrowTail(2),arrowHead(2)],...
        [arrowTail(3),arrowHead(3)],'Color','m');
    hold off;
end

function OUT=r2d(ANGLE)
% Converts radians to degrees

    OUT = ANGLE*180/pi;
end

function OUT=d2r(ANGLE)
% Converts degrees to radians

    OUT = ANGLE*pi/180;
end

function OUT=rot(AXIS,ANGLE)
% Calculates the basic rotation matrix numerically
% AXIS is either 'x', 'y', or 'z'.
% ANGLE is in degrees. 

    if (length(AXIS)>1 | length(ANGLE)>1)
        error('Input sizes must be 1x1');
    end

    ANGLE = d2r(ANGLE);

    if AXIS=='x'
        OUT=[          1,           0,           0;...
                       0,  cos(ANGLE), -sin(ANGLE);...
                       0,  sin(ANGLE),  cos(ANGLE)];
    elseif AXIS=='y'
        OUT=[ cos(ANGLE),           0,  sin(ANGLE);...
                       0,           1,           0;...
             -sin(ANGLE),           0,  cos(ANGLE)];
    elseif AXIS=='z'
        OUT=[ cos(ANGLE), -sin(ANGLE),           0;...
              sin(ANGLE),  cos(ANGLE),           0;...
                       0,           0,           1];
    else
        error('AXIS input must be x, y or z');
    end
    
end

function OUT=eulseq(SEQUENCE,ANGLES)
% Calculates rotation matrix corresponding to given Euler Sequence
% SEQUENCE and angles ANGLES.
% SEQUENCE is 1xN char array composed of chars 1, 2, 3 only. For
% example '123' or '32' etc.
%
% ANGLES is 1xN array of angles in degrees. ANGLES(i) is the rotation
% about axis defined by SEQUENCE(i).

    if length(SEQUENCE) ~= length(ANGLES)
        error('SEQUENCE and ANGLES must be of same length.');
    elseif ~isempty(regexpi(SEQUENCE,'[^123]'))
        error('SEQUENCE must only contain 1, 2, and 3 characters.');
    else
        C=eye(3);
        
        str='xyz'; %used to convert 123 to xyz
        
        for k=1:length(SEQUENCE)
            C=C*rot(str(str2double(SEQUENCE(k))),ANGLES(k));
        end
        OUT=C;
    end
end

You should copy/paste all the code to a new m-file and save m-file as "MessingWithCoordinateSystems.m" and then run the code. What the main code does is as follows:
  1. First an absolute coordinate system (csys) is defined. It is named csys_ABS.
  2. A new csys is defined by rotating csys_ABS with '21' euler sequence by 90 and 45 degrees respectively, and later translating the rotating csys in its z direction by 2 units.
  3. A vector is defined from absolute csys origin to new csys origin.
  4. Everything is plotted
The output looks like this (after using the rotation tool in figure toolbar):
Figure 1. Output of code snippet showing absolute csys, transformed csys and the vector connecting their origin

My coordinate systems are structures with two properties: Origin and Orientation. In the case of absolute coordinate system, origin is zero vector and orientation is the identity matrix. All other coordinate systems and vectors are defined with respect to this absolute coordinate system. With the functions given you can do the followings:
  • eulseq: You can obtain rotation matrix for any Euler angle sequence.
  • rot: You can obtain basic rotation matrix around any single axis.
  • d2r, r2d: Converts degrees to radians and vice versa.
  • plot_vector, plot_csys: Plots csys objects and vectors on figure.
  • rotate_csys: Rotates a csys by a given rotation matrix. Rotation matrix can be obtained from eulseq or rot or any other way.
  • translate_csys: Translates a csys by a vector. The vector may be resolved in absolute coordinate system or the coordinate system to be translated or any other csys.
  • create_csys_object: Creates csys object with required structure.

Wednesday, September 5, 2012

Excel ile KPSS tercihleri

Şöyle oluyor, eşim için 5 tercih süreci geçirdiğimiz için, "bu tercih işini nasıl daha kolaylaştırırız da 150 küsür sayfalık listeler kodlar arasından kolayca sıyrılırız" sıkıntısına şöyle bir çözüm geliştirdim. Belki işinize yarar:

Özet geçmek gerekirse:
ÖSYM kılavuzunu chrome'da açın ve tercihlerin olduğu sayfaları chromeun"Save as PDF" komutu ile yazdırın. Oluşturduğunuz pdfi açıp herşeyi seçin, kopyalayın ve bir text dosyasına yapıştırın. Text dosyasını excelde space delimited olarak açın ve xlsx olarak kaydedin. Tüm hücreleri seçerek "Conditional Formatting->Highlight Cells Rules->Text that Contains..." menülerini kullanarak tercih yapacağınız ili ve size uyan nitelik kodlarını değişik renklerle işaretleyin. Excel satırlarını tarayarak şehir ve nitelik kodlarının eşleştiği satırları (renklendirme tespit etmenizi kolaylaştıracak) seçip kopyalayarak yeni bir sayfaya yapıştırın. Tercih listeniz artık önünüzde. Sıralamaya karar vermeniz yeterli.

Uzun uzadıya:

Friday, August 17, 2012

MS-DOS zamanından kalan alışkanlıklar ve faydaları

İlk yazı ilk deneme. Şimdilik konsept olmadan yazacağım, ilerde belki bir format bişey oluşur. Biraz DOS günlerine dönelim bugün. Sene 1990, yaş 5, daha varlığından bile haberimiz yokken, babam eve bilgisayar diye birşey getirmiş. 640kb ram, 10mb harddisk, ekran kartı hercules+desteklediği kadar da cga. işlemci intel 8088. Sadece klavye vardı o zamanlar, mouse'u çok daha sonra paint benzeri bir çizim programını çalıştırabilelim diye doğum günü hediyesi olarak alınmıştı. İşletim sistemi MS-DOS, zira Windows ile de yıllar sonra ortaokul çağlarında gazeteden topladığımız kuponlar ile aldığımız Pentium 75 bilgisayarda tanışacağım.

Bana faydası ne oldu peki bu bilgisayarın ilkel haliyle tanışmanın? Bilgisayarla birlikte babam sağolsun birkaç tane de Basic kitabı getirdi. O zamanlar oyun öyle kolay bulunmuyor, değişik dergilerin arkasında oyun listeleri var, karşılarında kaç disket olduğu yazıyor vs. oradan seçiyorsun. Bu Basic kitaplarının içinde ve arkasında oyun örnekleri olurdu. 50 satır ile 15000 satır arasında değişebilen kod ihtiva eden bu örnekleri basic derleyicisine yazıp da run ettiniz mi ASCII karakterleri ile bezeli türlü türlü oyun çıkardı. Önceleri direk kopyala-yapıştır usulü az satırlı örnekleri yazarak başladık işe. Sonra uzun olanlara geçtik. Sonra o kopyaladağımız satırları anlamaya çalıştık. Sonra kitaptaki yazım hataları nedeniyle run ettiğimizde hata veren satırları düzeltmeye başladık. Paralelden MS-DOS komutlarını da öğrenmeye başladık. 

Kıssadan hisse, programlamayla erken yaşta tanıştık. Peki yıl 2012, bize ne MS-DOS'tan? O gün öğrendiğim komutları hala kullanıyorum çünkü ben. Windows'un kolay ulaşılabilen arayüzleri ile yapamadığım şeyleri iki tıkla yapmamı sağlıyor çünkü. İki örnek verip ilk yayınımı tamamlayayım.

Örnek 1: Çalıştığım işte, embedded windows xp işletim sistemi kurulu bir cihazın içerisine C++'ta derlediğim exeyi ve diğer config klasörlerini kopyalıyorum ve sonra exeyi çalıştırıyorum. Gel gelelim binadaki bir elektrik arızasından dolayı bilgisayarın içindeki ekran kartının bir kısmı yandı ve ekrana görüntü alamıyoruz. Windows açılıyor ancak birşey göremediğimiz için ne exeyi ne klasörü kopyalayamıyorum. Çözüm basit. Laptopta hemen bir hebe.txt dosyası oluşturdum. İçine o yıllar öncesinden hatırladığım üç komutu yazdım:
     rd /s /q "c:\MyFolder
     md "c:\MyFolder"
     xcopy /e "h:\MyFolder" "c:\MyFolder"
Sonra txt'yi bat yaptım. Artık windows açılınca yapacağım şu: "Windows tuşu+R" ile run penceresini açıp oraya "h:\hebe.bat" yazmak. Yazdığım kod istediğim kopyalama işlemini yapacak. Bu sayede yanan kart onarılana kadar işe devam.

Örnek 2: Laptopun şu anda bebişin resimleri ile dolu. Hanımın telefondan gelen, benim telefondan gelen, fotoğraf makinasından gelen vs. Toplasan 500'e yakın foto. Fotoğraf çeken her alet fotoğraflara artan ardışık numaralar verdiği için zaman sırasıyla fotoğrafları gezmek kolay oluyor. Ancak evde iki iphone olunca, numaralar çakıştı ve google drive'a aktarmaya çalışınca kimi dosyaların sonunda (2) (3) eklendi. Bu da set halinde çekilmiş resimlerin arasına başka setlerin karışmasına neden oldu. Kısacası hoşuma gitmedi. Ben de eşimin telefonundan gelenler ile kendi telefonumdan gelenleri farklı isimlendirmeye karar verdim. Resimlerin adı "IMG-xxxx.JPG" formatında. Yine bir hebe.txt oluşturdum ve içine
     ren *.JPG uiIM*.JPG
yazdım. Dosyanın sonunu bat yapıp dosyaya çift tıklayınca 100 kadar resmin adı 1 saniyede "uiIMxxxx.JPG" formatına değişti. Aynı şeyi eşimin klasörü için de yaptım ve kısa sürede 100 kadar dosyanın adını değiştirdim. Bildiğim kadarıyla bunu Windows'un size sunduğu göz önündeki toollarla yapamıyorsunuz.

İşte böyle. Başka örnekler de aklıma geldi yazarken ama neyse. İlk yazıdan herkese selam olsun.