كيف يعمل شريط بقيادة العنوان؟


ربما هذا السؤال "كيف يعمل" يبدو سخيفا للكثيرين. الجواب واضح تقريبًا: يتكون شريط LED القابل للتحكم من مجموعة من "المصابيح الذكية" المتصلة في سلسلة. يمكن ملاحظة ذلك ببساطة من خلال النظر إلى جهاز الشريط. يمكنك رؤية الدوائر الصغيرة الفردية ملحومة في حلقة مرنة ، يمكنك رؤية الاتصالات: الدوائر الصغيرة متصلة في سلسلة بثلاثة أسلاك فقط ، واثنان منها قوة وأرضية. سلك واحد فقط ينقل بيانات لون البكسل. كيف هذا؟ ما هو LED الذكي؟

بعد ذلك ، سأتحدث عن بروتوكول نقل البيانات المستخدم في شريط LED استنادًا إلى WS2812B ، علاوة على ذلك ، سأقوم تقريبًا بإنشاء "شريحة شريط LED" الخاصة بي في شريحة FPGA.

لذلك ، يستخدم الشريط الإرسال التسلسلي من خلال إشارة بيانات واحدة.

يرسل البتة صفر كنبضة موجبة قصيرة وقفة أعرض مرتين تقريباً من النبضة. يتم إرسال وحدة البت كدفع إيجابي واسع وقفة قصيرة:



إذا لم يكن هناك إرسال لأكثر من 50 ميكروثانية ، يعود الشريط إلى حالته الأصلية ، جاهزًا لقبول وحدات البكسل بدءًا من الأول.

كل 24 بت في تسلسل هي 3 بايت لثلاثة ألوان RGB. وفي الواقع سيكون التسلسل GRB. الجزء العالي من G7 يأتي أولاً.

تسلسل أول 24 بت هو بكسل واحد ، والذي سيتلقى أول مؤشر LED في الشريط. حتى يتم إشباع مؤشر LED الأول ، فإنه لا ينقل البيانات إلى مؤشر LED التالي. بعد أن يتلقى LED الأول حصته من 24 بت RGB ، فإنه يفتح الإرسال إلى التالي. بشكل أساسي ، يمكن للمرء أن يتخيل تسلسلًا من مصابيح LED كسلسلة من أباريق مملوءة بالماء على التوالي:



الأول ، ثم الثاني ، ثم الثالث ، وهكذا ، سيتم ملؤه بدوره.

وبالتالي ، أعتقد أنه تم تسوية بروتوكول النقل.

هل من الممكن محاولة تصميم هذا "LED الذكي" بنفسك؟ بالطبع ، هذا ليس له معنى عملي كبير ، ولكن بالنسبة للتعليم الذاتي وتوسيع آفاق المرء ، فهذه مهمة مثيرة للاهتمام. دعونا نحاول وصف منطق الشريحة بلغة البرمجة Verilog HDL. بالطبع ، لن يكون هذا تصميم رقاقة حقيقي ، سيكون هناك قيود. واحدة من أهم القيود - سأحتاج إلى ساعة خارجية لدائرتي الدقيقة. في LED الذكي الحقيقي ، يوجد هذا المولد أيضًا ، ولكنه مدمج بالفعل في الشريحة.

لنبدأ وحدة Verilog مثل هذا:

module WS2812B(
	input wire clk,
	input wire in,
	output wire out,
	output reg r,
	output reg g,
	output reg b
);

أعتقد أن كل شيء واضح هنا: تردد الساعة clk وإشارات الإدخال والإخراج لـ "LED الذكي" داخل وخارج ، وبطبيعة الحال ، إشارات الإخراج r ، g ، b التي من خلالها سوف تتحكم في المصابيح الخارجية الحقيقية باللون الأحمر والأخضر والأزرق.

سألتقط إشارة الإدخال في سجل إزاحة من بتين ومن الحالة الحالية في هذه البتات الملتقطة يمكنني تحديد بداية حافة موجبة للإشارة في:

reg [1:0]r_in = 0;
always @( posedge clk )
	r_in <= { r_in[0],in };

wire in_pos_edge; assign in_pos_edge = (r_in==2'b01);

بالإضافة إلى ذلك ، من المهم تحديد حالة إعادة تعيين الشريط عندما تتوقف وحدة تحكم التحكم مؤقتًا قبل بدء إرسال جديد:

localparam reset_level = 3000;
reg [15:0]reset_counter = 0;
always @( posedge clk )
	if( r_in[0] )
		reset_counter <= 0;
	else
	if( reset_counter<reset_level )
		reset_counter <= reset_counter+1;

wire reset; assign reset = (reset_counter==reset_level);

علاوة على ذلك ، من الحافة الإيجابية in_pos_edge ، من الضروري تحمل بعض التوقف المؤقت من أجل الحصول على لحظة إصلاح بت جديد:

localparam fix_level   = 50;
reg [7:0]bit_length_cnt;
always @( posedge clk )
	if( in_pos_edge )
		bit_length_cnt <= 0;
	else
	if( bit_length_cnt<(fix_level+1) && !pass )
		bit_length_cnt <= bit_length_cnt + 1;

wire bit_fix; assign bit_fix = (bit_length_cnt==fix_level);

يعتبر عدد البتات المستلمة بالفعل في الشريحة كما يلي:

reg pass = 0;
reg [5:0]bits_captured = 0;

always @( posedge clk )
	if( reset )
		bits_captured <= 1'b0;
	else
	if( ~pass && bit_fix )
		bits_captured <= bits_captured+1'b1;

يتم تقديم إشارة مرور مهمة هنا ، والتي تحدد فقط إعادة توجيه دفق الإدخال إلى الإخراج. بعد قبول بت 24 × بكسل ، يتم تعيين إشارة المرور إلى واحدة:

always @( posedge clk )
	if( reset )
		pass <= 1'b0;
	else
	if( bits_captured==23 && bit_fix )
		pass <= 1'b1;
		
reg pass_final;
always @( posedge clk )
	if( reset )
		pass_final <= 1'b0;
	else
	if( r_in!=2'b11 )
		pass_final <= pass;
		
assign out = pass_final ? in : 1'b0;

يتم مضاعفة الإدخال إلى الإخراج عندما تكون إشارة pass_final واحدة.

حسنًا ، بالطبع ، نحتاج إلى سجل تغيير ، حيث يتم تجميع 24 بتة مستلمة من البكسل:

reg [23:0]shift_rgb;
always @( posedge clk )
	if( bit_fix )
		shift_rgb <= { in, shift_rgb[23:1] };

reg [23:0]fix_rgb;
always @( posedge clk )
	if( bits_captured==23 && bit_fix )
		fix_rgb <= { in, shift_rgb[23:1] };

عند استلام 24 بتة ، يتم نسخها إلى سجل 24 بت النهائي أيضًا.

الآن تبقى المسألة صغيرة. من الضروري تنفيذ إشارة PWM (تعديل النبض العرضي) لنقل السطوع إلى مصابيح LED الخارجية الحقيقية وفقًا لبايت RGB المستقبلة:

wire [7:0]wgreen; assign wgreen = { fix_rgb[0 ], fix_rgb[1 ], fix_rgb[2 ], fix_rgb[3 ], fix_rgb[4 ], fix_rgb[5 ], fix_rgb[6 ], fix_rgb[7 ] };
wire [7:0]wred;   assign wred   = { fix_rgb[8 ], fix_rgb[9 ], fix_rgb[10], fix_rgb[11], fix_rgb[12], fix_rgb[13], fix_rgb[14], fix_rgb[15] };
wire [7:0]wblue;  assign wblue  = { fix_rgb[16], fix_rgb[17], fix_rgb[18], fix_rgb[19], fix_rgb[20], fix_rgb[21], fix_rgb[22], fix_rgb[23] };

reg [7:0]pwm_cnt;

always @( posedge clk )
begin
	pwm_cnt <= pwm_cnt+1;
	r <= pwm_cnt<wred;
	g <= pwm_cnt<wgreen;
	b <= pwm_cnt<wblue;
end

يبدو أن هذا كل شيء.

تبقى تفاصيل صغيرة - كيف تجرب كل ذلك؟

أخذت بعض اللوحات الأم البسيطة مع FPGA MAX II (هذه هي بطاقات سلسلة Mars rover) وأضفت عليها جميعًا بالمشروع باستخدام رمز Verilog هذا. كان هناك بالفعل 8 مصابيح LED على اللوحات ، لكنها كانت كلها صفراء. في كل من الألواح ، قمت باستبدال 3 مصابيح LED بـ R ، G ، B. لقد قمت بتوصيل الألواح في سلسلة ، علاوة على ذلك ، قمت بتوصيلها بشريط LED حقيقي. وبالتالي ، قمت بإطالة الشريط الحقيقي باستخدام مصابيح LED الخاصة بي.

تحول هذا الاتصال على النحو التالي :



في الواقع ، يبدو كما يلي:



الآن ، بتطبيق صورة معينة على الشريط ، أرى أن "مصابيح LED الذكية" تتصرف تمامًا مثل تلك الموجودة في الشريط:


اتضح أن المنطق الذي طبقته في FPGA يعمل بكامل طاقته! كمقاربة أولية ، تمكنت من القيام بشيء مماثل لرقاقة LED ذكية حقيقية.

في الواقع ، أنا أحب شرائط LED. على أساسها ، يمكن للجميع اختراع شيء خاص بهم: الإضاءة الذكية ، والشاشات ، وتأثيرات Ambilight. بمجرد أن قمت بتنفيذ موسيقى ملونة على شريط LED يشغل FPGA. لكن هذه قصة أخرى .

All Articles