نویز | آموزش AVR | آموزش میکرو | میکروکنترلر

وبلاگ آموزشی احسان نوری ::: Ehsan Nouri's Weblog

نویز | آموزش AVR | آموزش میکرو | میکروکنترلر

وبلاگ آموزشی احسان نوری ::: Ehsan Nouri's Weblog

" نویز رسانه ای است برای آموزش آسان مفاهیم میکروکنترلر و الکترونیک "

دریافت مستندات
آخرین نظرات
  • ۲۰ خرداد ۰۰، ۲۰:۴۹ - حسام الدین سلطانی
    خعلی عالی
  • ۲ ارديبهشت ۰۰، ۱۸:۱۱ - حسام الدین سلطانی
    خیلی عالی

 

هفتمین قسمت از کارگاه عملی با عنوان "کار با تایمر/کانتر صفر در مد PWM" در ادامه مطلب قابل مشاهده است.

 

پس با ما در ادامه مطلب همراه باشید ...

 

سلام

 

در قسمت قبلی با مد PWM آشنا شدین.

 

 

الان وقتشه که برنامه نویسیشو هم یاد بگیرین.

 

اما اول از همه بریم ببینیم که اصلا اوضاع مد PWM در میکروکنترلرهای AVR چطور هست.

 

انتخاب تایمر/کانتر در میکروکنترلر AVR :

 

گفتیم که میکروکنترلر AVR دارای سه تایمر/کانتر هست:

  • Timer/Counter 0
  • Timer/Counter 1
  • Timer/Counter 2

هر سه تای این تایمر/کانترها از PWM پشتیبانی میکنند.

تایمر/کانتر 0 و 2 هشت بیتی هستند و تایمر/کانتر 1 شونزده بیتی !

 

مِن باب یادآوری : هشت بیتی از 0 میشماره تا 255 و شونزده بیتی از 0 میشماره تا 65536 .

 

طبق معمول یه مسئله تعریف میکنیم و اقدام به حل کردنش میکنیم.

 

تعریف مسئله :
 

در نظر داریم با استفاده از تایمر/کانتر صفر، یک موج PWM با فرکانس 50 هرتز و دیوتی سایکل 30 درصد بسازیم.

 

اول یه کم محاسبات انجام میدم تا متوجه بشید که اصلا معنای فرکانس و دیوتی سایکل در اینجا چی هست ؟!

 

 

F= 50 Hz

T = 1/50 Hz = 0.02 s = 20 ms

 

 

 

T = Ton + Toff = 20 ms

 

 

Duty Cycle = 30 %

 

Ton = 6 ms

Toff = 14 ms

 

اینا هم خداییش توضیحی لازم نداره !

یه دو دوتا چهارتای ساده ست !

 

از کلیه این محاسبات نتیجه گرفتیم که مدت زمانی که در یک دوره موج خروجی باید سطح یک (5+ ولت) داشته باشه 6 میلی ثانیه است !

و همچنین مدت زمانی که موج خروجی باید سطح صفر (0 ولت) داشته باشه نیز 14 میلی ثانیه است.

 

داریم راجع به موج مربعیه صحبت میکنیمااااا !!!

 

کلیه اینکار ها انجام میشه تا دیوتی سایکل 30 درصد و فرکانس 50 هرتز ساخته بشه.

 

از اینجا به بعد باید رجیسترهای مربوط به تایمر/کانترمونو برنامه ریزی اولیه کنیم.

لازم بذکره که با استفاده از مد PWM کلیه محاسبات و فرایند تولید موج PWM توسط پردازنده میکروکنترلر انجام میشه و نیازی به برنامه نویسی برای این کار نیست.

 

از تایمر/کانتر شماره صفر استفاده میکنیم.

 

یه سری بزنیم ببینیم رجیسترهاش چیا بودن ؛

 

بررسی رجیستر TCCR0 :

 

قبل ترها در مورد تایمر/کانتر صفر به تفصیل توضیح داده شد. میتونید اینجا ببینید : بررسی تایمر/کانتر صفر

 

اما بحث ما سر دو تا بیت با عنوان های WGM00 و WGM01 هست.

 

بیت های 3 و 6 ؛ WGM01:0 – Waveform Generation Mode :
 

 

میبیند که انتخاب مد PWM با انتخاب WGM01:00 بصورت 01 یا 11 قابل انجامه !

 

بیت های 4 و 5 ؛ COM01:00 – Compare Match Output Mode :

 

 

جدول بالا مربوط به مد Fast PWM تایمر/کانتر صفر میباشد.

یادآوری : یه پایه ای داریم به نام OC0 که به پایه مقایسه ای خروجی تایمر/کانتر صفر معروفه !

برای این کاری که ما میخوایم انجام بدیم از جدول بالا سطرهای سوم یا چهارم رو انتخاب کنیم.(همون Inverting و Non-Inverting)

 

گفتیم که کلیه فعالیت های مربوط به محاسبات مد PWM توسط CPU و بصورت کاملا سخت افزاری انجام میشه،یعنی مثل مدهای کاری دیگه تایمر/کانتر یعنی Normal و CTC لازم نیست که زیاد درگیر برنامه نویسی بشیم و با تنظیم رجیسترها به خواسته مون میرسیم !

 

برای ساخت موج با دیوتی سایکل و فرکانس مورد نیاز تنها کاری که باید انجام بدیم اینه که مشخص کنیم که چه بلایی سر پایه OC0 مون بیاد!تا در خروجی یه شکل موج با مشخصات دلخواه داشته باشیم.

اگه حالت 10 انتخاب بشه،پایه OC0 پس از تطبیق با مقدار مقایسه ای مون،صفر بشه و در نقطه BOTTOM یک بشه.

اگه حالت 11 انتخاب بشه،پایه OC0 پس از تطبیق با مقدار مقایسه ای مون،یک میشه و در نقطه BOTTOM صفر بشه.

 

جدول بالا برای مد Fast PWM بود.

اگه خواستیم از مد Phase Correct PWM استفاده کنیم،جدول مربوط به بیت های COM01:00 به قرار زیر میشود :

 

 

در ضمن یادتون نره که بیت های CS00 و CS01 رو هم برنامه ریزی کنید.

 

تا اینجا فقط،تایمر/کانتر صفرمونو در مد PWM تنظیم کردیم و بهش گفتیم میخوایم ازش برای ساخت موج PWM استفاده کنیم.

اما بهش نگفتیم که چه دیوتی سایکلی داشته باشه !

خودش هم که علم غیب نداره! باید بهش بگیم !!! laugh

 

نکته جالبی که وجود داره اینه که هر عددی که در رجیستر OCR0 ما ذخیره بشه نقش دیوتی سایکلو بازی میکنه !

یعنی چی ؟

ببینید :

 

OCR0 = DutyCycle = 30 % = 30 % of 255 = 76.5 ==> تقریبا 76

 

خب ...

بریم سراغ برنامه نویسی ...

 

#include <mega32.h>

توضیح نمی‌دم cheeky

 

void timer0_configuration (void){
TCCR0 = (1<<WGM00) | (1<<WGM01) | (1<<COM01) | (1<<CS00); //Fast PWM Mode,Non-Inverting,No Presacling
DDRB = (1<<PB3); //OC0 Pin Set As Output
}

یه تابع تعریف کردیم به نام timer0_configuration که کلیه تنظیمات مربوط به تایمر/کانتر صفر در اون انجام میشه.

همه چی واضحه(البته برای اونایی که مطالب وبلاگو از اول دنبال کردند !)،ضمن اینکه روبروی هر خط توضیحاتشو هم نوشتم !

 

پین B3 رو هم بعنوان خروجی تنظیم کردیم.

 

void main(void){

timer0_configuration();

while(1){  //Loop For Ever

OCR0 = 76; // Dutycycle

}

} 

این هم تابع main ماست.

اول داخلش تنظیمات تایمر/کانتر صفر فراخوانی شد.

بعد از اون یه حلقه بی نهایت گذاشتیم و داخلش رجیستر OCR0 رو طبق اون نکته ای که گفتم با مقدار دیوتی سایکل برابر قرار میدیم.

 

والسلام ...

با این برنامه یه موج مربعی در حالت Non-Inverting ساختیم که دیوتی سایکل 30 درصد و فرکانس 50 هرتز داره.

 

یه مثال دیگه میزنم؛که اینقدر نگید بیشتر مثال بزن !

 

مسئله :

میخوایم یه فلاشر با LED بسازیم.

اما اشتباه نکنید !

منظور ما فلاشری مثل فلاشرهای قبلی نیست.

میخوایم نور LED رو کم و زیاد کنیم.

 

برنامه :

 

#include <mega32.h>
#include <delay.h>

timer0_configuration(void){
TCCR0 = (1<<WGM00)|(1<<WGM01)|(1<<COM01)|(1<<CS00);
DDRB = (1<<PB3);
}

unsigned int brightness;

void main(void){

timer0_configuration();

while(1){  //Loop For Ever

for(brightness=0;brightness<255;bightness++){  // Loop For Increasing Brightness

OCR0 = brightness;
delay_ms(10);

}
for(brightness=255;brightness>0;brightness--){  //Loop For Decreasing Brightness

OCR0 = brightness;
delay_ms(10);

}
}

}  

 

برنامه از دو تا حلقه For تشکیل شده که اولی وظیفه‌ی افزایش نور LED رو به عهده داره و دومی وظیفه‌ی کاهش نور LED رو.

یه تاخیر 10 میلی ثانیه ای هم گذاشتیم برای اینکه متوجه این کاهش و افزایش بشیم !

 

خب این هم از بنامه نویسی و کلا مد PWM...

 

یه نکته ای رو هم خدمتتون عرض کنم،اونم اینکه هیچ وقت با خوندن متنای بنده هوا برتون نداره !

تمامی این مطالبی که برای PWM مطرح و آموزش داده شد،جزو مسائل دم دستی و در ساده ترین صورت ممکن بود.

اما اگه کسی بخواد از زیر و بم PWM سر در بیاره،باید بیشتر تحقیق کنه و اگه علاقه مند بود از دیتاشیت هم استفاده کنه.

کلا بحث نکته خیزیه!(البته مخاطب بنده کسانی نیست که برای پاس کردن درس این پستو میخونن ! angry)

اینو گفتم که بدونین قضیه به این سادگی هم نیست.frown

 

 

فعلا ...

سلام
آقا ادامش چی شد
به به عالی بوووووووود

پاسخ:
ادامه ؟؟؟
سلام 
واقعا دست گلت درد نکنه. لطفاً اگه ممکنه  اسکن صفحه کلید رو توضیح بده، با تشکر فراوان خدا خیرت بده
پاسخ:
اگر شد، در آینده ...
سلام
سپاسگذار. واقعا استفاده کردیم

پاسخ:
:)
آقا خدا خیرت بده عالی بود
مطلب بعدی کی منتشر میشه
پاسخ:
هر وقت آماده بشه !

سلام

دوست عزیز . در چند روز گذشته تمام مطالب وبلاگتون را مطالعه کردم. بسیار شیرین و روان پر محتوا نوشته بودین. امیدوارم همواره تن سالم و روانی آسوده داشته باشین . ممنونم


پاسخ:
سپاس
اگه نخوایم این تاخیر رو ببینیم چیکار میکنیم,یعنی این تغییر رنگ مثل چشمک زدن نشه و خیلی اروم رنگها تغییر کنن,اگه در حد میکرو بدیم دیگه چشمک نمیزنه
پاسخ:
الان چشمک میزنه مگه ؟
اگه چشمک میزنه،تاخیرو کم کنید.
سلام
ممنون از مطالب خوبتون
من یه برنامه نوشتم که هر دقیقه 1واحد روی7سگمنت اضافه میکنه
اما مشکل اینجاست که تقریبا هرثانیه میکرو ریست میشه
ولی واچداگ فعال نیست و پایه ریست پول اپ شده همچنین هیچ مزاحمی برای پایه ی ریست وجود نداره
در ضمن میکرو atmega8هست ممنون میشم راهنمایی کنید
پاسخ:
منبع تغذیه تون رو عوض کنید.
از خازن صافی 470 میکرو فاراد موازی با خروجی رگولاتور استفاده کنید.
سلام دوست عزیز
بهت تبریک می گم وبلاگ خیلی خوبی داری,
واقعا کارت درسته که وقتی عبارت "آموزش avr" رو تو گوگل می زنی اولین گزینه وبلاگ توئه!!!!!!!
من تازه با وبلاگ تو آشنا شدم
من دانشجو نیستم و فارغ التحصیل شده ام ولی غنای مطالب تو منو به خودش جذب کرد
من هم زمان دانشجویی وقتی دنبال مطلبی خاص می گشتم و کتابی سراغ نداشتم که همه رو بشه ازش فهمید واسه همین شاید از چند کتاب می خوندم بعد با زبان خودم اونو می نوشتم والحق که کار زیبایی از آب در می اومد
سه تا پیشنهاد دوستانه داشتم برات:

1-اولش این که اگه واقعا می خوای این راه رو ادامه بدی زیاد بین مطالبت تاخیر نینداز و اگه هر هفته یه مطلب بذاری عالی می شه(مثلا فرض کن پست جدید هر هفته سه شنبه ساعت 18 منتشر بشه)

2-دوم این که چون واقعا مطالبت ارزش داره اون ها رو vip کن بعضی ها رو هم به عنوان نمونه بدون vip(مطمئن باش اگه مورد اول رو ادامه بدی این کار جواب می ده,یکیش من خودم vip می شم یه حسن دیگه vip اینه که کاربرا احساس هویت می کنند!!!!!؟؟؟؟؟؟؟؟!!!!)باز هم می گم vip برات جواب می ده چون دیگه الآن وبلاگت شناخته شده است(مورد اول جستجوی گول)و ضمنا الآن یه دوره زمونه ای شده که بعضی سایت ها حتی واسه قصه حسن کچل هم vip می ذارن چرا شما با این همه زحمت نذارید؟؟؟

3-مطالب رو به سایت منتقل کن که تو ایران از اعتبار بیشتری برخورداره و در ضمن اون این وبلاگ رو هم ادامه بده یعنی به همدیگه لینکشون کن.

و اما یه هشدار دوستانه داشتم

1-تو ایران که قانون کپی رایت اصلا وجود نداره شک نکن و باز هم شک نکن که مطالبت رو سایت های دیگه کپی خواهند کرد پس مطالبت رو تو فرمت pdf منتشر کن که تو background اش اسم وبلاگ ات نوشته شده بعد هم pdf ها رو رمز بذار تا نتونن کپی پیست کنند(مطمئنا کپی کنندگان حال تایپ مطالب رو ندارند و فقط دنبال کپی هستند)

این حرف ها رو دوستانه وار گفتم چون واقعا دیدم که واسه پست هات وقت می ذاری و مطالبت با ارزشه و به نظر من اگه این موراد رو انجام بدی واسه خودت هم انگیزه مضاعفی پیش می آد.
موفق باشی

پاسخ:
سلام
مطالبتونو خوندم.
ممنون که وقت گذاشتین و توضیح دادین.
گرچه این مسائلی که بیان کردین درسته،ولی شرایط ایده آل نیست !!!
گر نخوایم متوجه این کاهش و افزایش بشیم,تاخیر رو روی چند بزاریم؟
در حد میکرا بزاریم دیگه چشمک نمیزنه؟
پاسخ:
جواب دادم
سلام 
خواهشمندم، اگه ممکنه در خصوص ارتباط کارت حافظه با avr و نحوه خواندن فایل ذخیره شده (روی کارت ) توسط نرم افزاری مثل Excel توضیحی بدهید خیلی ممنون میشم.
پاسخ:
در آینده انشاالله
خیلی از مطالبتون استفاده کردم ممنون خسته نباشید
پاسخ:
تشکر
سلام خیلی از مطالب شما استفاده کردم لطفا بازم  ادامه بدین
پاسخ:
انشاالله !
سلام
ممنون بابت آموزش روان و خوبتون
فقط من توی مثال اولی متوجه نشدم که چطور فرکانس موج 50 هرتز میشه؟ یعنی ما اصلا محاسباتی برای این کار انجام ندادیم...اصلا فرکانس کاری خود تایمر هم مشخص نکردیم...
پاسخ:
میشه بگید 20 میلی ثانیه رو از کجا آوردیم ؟؟؟؟
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
// Place your code here

timer0_ov++;

}
////////////////////////////
while (1)
      {
       
      TCCR0=0x06;                                     
      #asm("sei")
      delay_ms(50);
      #asm("cli")
      in_freq=20*(timer0_ov*256+TCNT0);  
        
      //delay_ms(250);
      TCCR0=0x00;                                     
      timer0_ov=0;
      TCNT0=0;                                       

      humidity=(-0.075872)*(in_freq-7351);  }}


سلام مهندس جان

میشه بهم بگین تو این برنامه که وقفه فعال شده و 50میلی بعد غیر فعال شده دلیلش چیه؟

اصلا این یعی چی؟

واسه راه اندازی سنسور HST1101 هستش

ممنون میشم راهنمایی کنید
پاسخ:
سوال پروژه ای ممنوع !!!
سلام
خییییییییییییییییییلی خییییییییییییییییییییلی خسته نباشی و دمت گرم سایتت عالیه کار خودتم درسسسسته..
حدود یکسال پیش اومدم اینجا رو دیدم با اینکه تا حدود زیادی با یرنامه نویسی و AVR  آشنایی داشتم چون با پیچدگیها و مشکلات زیاد یاد گرفته بودم مطالب واسم بصورت فرّار بود و بعد از یه مدت بخاطر مشغله های زندگی فراموش میشد.. بعد از خوندن مطالب سایتتون یه سازماندهی و شکلگیری خوبی از این مباحث تو ذهنم ایجاد شد که اونم بخاطر زبان سلیس و عامیانتون تو گفتن مطالبه ... خواستم تشکر کنم ازتون بخاطر معلم خوب بودنتون...
میلاد - شیراز ;)
پاسخ:
ممنون
موفق باشید.
لطفا آموزش برنامه نویسی تابلو ثابت ال ای دی رو شروع کنید
پاسخ:
؟
چه ربطی داره ؟؟؟
سلام 
الان خوندن تمام پستهاتونو تموم کردم ، واقعا ازتون تشکر میکنم ، شیوه و مطالب آموزشتون عالیه ، بی صبرانه منتظر مطالب جدیدتون هستم ، بازم مرسی
پاسخ:
تشکر
سپاس از مطالب مفیدتون منتظر مطالب جدیدتون هستیم 
پاسخ:
تنکس
سلام احسان جان
به جان من خیلی مردی
خیلی از وبلاگت خوشم اومد
تمام پست هات رو خوندم
واقعا کسایی که قدرت رو نمیدونن قدر نشناسن
من خیلی دنبال پست های اموزشی avr گشتم ولی تو تنها مردی بین این همه کسایی که بلدن باهاش کار کنن
خیلی دوستت دارم
خیلی زیاد
خیل کمکم کردی من خیلی پیشرفت کردم
الان هم توی تیم رباتیک میخوام کار کنم
دستت درد نکنه
باز هم منتظر پست هات هستم
در مورد lcd های گرافیکی هم بیشتر توضیح بده اگر میشه و میتونی
دستت درد نکنه
خداحافظ
پاسخ:
ممنون،ممنون،ممنون

سلام، آقا بابت وبلاگ خوبتون بهتون تبریک میگم.

یه سوال ازتون داشتم. خواستم بدونم میشه یه موج مربعی با دیوتی سیکل و فرکانس متغیر ساخت؟

چون تا اونجایی که من اطلاع دارم توی مد PWM  فرکانس ثابته.

پاسخ:
پس مد Phase And Frequency Correct واسه چیه ؟
salam dash vaghan alie karet 
haminjori edame bede 
good luck

پاسخ:
سپاس
بسیار عالی بود ممنون..
سلام مهندس خسته نباشید میخاستم یک موج سینوسی درست کنم امکانش هست کمکم کنید!

تمامی مطالبتونو مطالعه کردم. بسیار عالی بود، خدا خیرت بده، لطفا ادامه بدهید، منتظر مطالب جدیدتون هستم.
مهندس جان سلام
آقا من لیسانس عمران هستم و شغلم اصلا مرتبط با الکترونیک نییییست! ولی علاقه مند به الکترونیک ام . همیشه تو اوقات فراغت مباحث الکترونیکی رو پیگیری میکنم،من مطالب منسجمی از الکترونیک بلد نبودم تا اینکه با سایت شما آشنا شدم.با تشکر از شما الان به حدی رسیدم که به دانشجو های الکترونیک  تو انجام پروژه هاشون کمک میکنم.
واقعا به قول یکی از دوستان:
تو ستاره شبهای منی:)
یعنی در این حد متشکرم ازت

واقعا بزرگی که مطالب رو در اختیار همه میذاری، خودم هیچ وقت فکر نمیکردم تو رشته ای که فارغ التحصیل نشدم ازش بتونم اینقدر پیشرفت کنم.در ضمن من بچینگ (کارخانه تولید بتن ) ، کنترل گلخانه شخصی خودم (500 متر مربع ) رو به صورت کاملا اتومات با atmega32 ساختم، فقط با مطالب شما دوست عزیز!
اگه کاری از دست من بر میاد بگو کامل در خدمتتم چون خیلی بهت مدیونم..  .

 استاد ندیده من هستی دستت بوسیدن داره *:*:*:
سلام مرسی  خیلی خوبه اموزش هاتون
به امید روزی ک کشور پیشرفته ای داشته باشیم

واقعا دستتون درد نکنه

مطالبتون خیلی عالی و قابل فهم ان.

موفق باشین.

تو برنامه اول کجاش نوشتی ۲۰ms؟فقط محاسبه انجام دادی!
خیلی عالیه
خیلی عالی هستین لطفا ادامه بدین
خب مگه نگفتین مقدار ocr0 دیوتی سایکلو تعیین میکمنه؟
خب باید دامنه ولتاز خروجی کم و زیاد بشه تا نور ال ای دی کم و زیاد بشه نه عرضش که آخه.....
مرسی. واقعا ممنون از این حسن رفتار. خدا بهت سلامتی بده
سلام
ممنون از مطالب خوبتون
من تازه با وبلاگ شما آشنا شدم و واقعا تحت تاثیر شیوه آموزشیتون قرار گرفتم
دستتون درد نکنه و امیدوارم باز به آموزش ادامه بدید هرچند میدونم که سخته

ممنون،
زحمت کشیدی ،
کارت درست ، خدا خیرت بده.
۲۶ تیر ۹۵ ، ۲۳:۳۷ ماتک صنعت
دمتون گرم، خیلی استفاده کردم
خییییییییلی خوب بود من تمام جلسات روخوندم وواقعا برام مفید بود امیدوارم موفق باشید:)
بسیار عالی
بی نهایت ممنون. واقعا نمیدونم چجوری میشه تشکر کرد. آموزش ها عالی بود. خسته نباشید.

ای .اش آرم رو هم همینجوری بهمون یاد میدادید.
خیلی ممنون از مطالب و آموزشهای مفیدتون...god bless U
سلام میشه اموزش ساخت موج مربعی با فرکانس متغیر رو بزارید
عالی بود
سلام. خیلی وقته وبلاگ متوقف شده... این اصلا خوب نیستا !!! واسه ما که طالب علمیم می گم و گرنه خودت که اوضاعت توپه

آنان که خاک را به نظر کیمیا کنند                 آیا شود که گوشه چشمی به ما کنند؟؟
۰۱ آذر ۹۷ ، ۱۱:۲۳ نیکا صفرپور👩
سلام ،من میخواستم بابت این همه مطالب با ارزش از شما تشکر کنم😆😀😃🙃
سلام یادتون رفته فرکانس موج خروجی تایمر رو بگید برای تایمرهای 8 بیتی فرکانس موج خروجی از رابطه زیر حساب میشه:
میشه Fclk/N*256

فرکانس پنجاه هرتز دقیقا کجای این کد تنظیم‌شده؟!

شما فقط دیوتی سایکلو رو سی درصد تنظیم کردید که

عالی مثل همیشه .با تو ضیحاتی که میدین ادم به میکرو بیشتر علاقه پبدا میکنه.مخصوصا میای اول توضیح میدی و بعد میای تو کد همونو توضیح میدی و تثبیت میشه.اگه واقن میتونی و وقتشو داری بی زحمت ادامه میکرو هم درس بده.

مسئله که مطرح کردین اشتباهه

بابا کارت خیلی درسته... کجا رفتی داداش

ارسال نظر

ارسال نظر آزاد است، اما اگر قبلا در بیان ثبت نام کرده اید می توانید ابتدا وارد شوید.
شما میتوانید از این تگهای html استفاده کنید:
<b> یا <strong>، <em> یا <i>، <u>، <strike> یا <s>، <sup>، <sub>، <blockquote>، <code>، <pre>، <hr>، <br>، <p>، <a href="" title="">، <span style="">، <div align="">
تجدید کد امنیتی