coding 3 color sorting machine with 3 servo motors and 1 tcs230 sensor with c++ on arduino - colors

I am now on my project that I need to sort the objects with different colors. I'll put all the objects on a conveyor and the sensor will read the color and the conveyor will transfer the object to the location that the box is place next the conveyor and there is servo motor I have installed to flick the object into the box. I found out that the code can not detect the color of the object(I already check that the sensor work properly).
#include <Servo.h> // include the Servo library
// Define the pins for the TCS230 color sensors
#define TCS230_S0 4
#define TCS230_S1 5
#define TCS230_S2 6
#define TCS230_S3 7
// Define the pins for the servo motors
#define SERVO1 9
#define SERVO2 10
#define SERVO3 11
// Define the RGB color values for each color to be sorted
#define RED_R 200
#define RED_G 0
#define RED_B 0
#define GREEN_R 0
#define GREEN_G 200
#define GREEN_B 0
#define BLUE_R 0
#define BLUE_G 0
#define BLUE_B 200
#define YELLOW_R 200
#define YELLOW_G 200
#define YELLOW_B 0
Servo servo1; // create Servo object for servo1
Servo servo2; // create Servo object for servo2
Servo servo3; // create Servo object for servo3
void setup() {
// initialize the TCS230 color sensor pins
pinMode(TCS230_S0, OUTPUT);
pinMode(TCS230_S1, OUTPUT);
pinMode(TCS230_S2, OUTPUT);
pinMode(TCS230_S3, OUTPUT);
// initialize the servo motor pins
servo1.attach(9);
servo2.attach(10);
servo3.attach(11);
}
void loop() {
int red, green, blue; // variables to store the color values
// read the color values from the TCS230 color sensor
digitalWrite(TCS230_S2, LOW);
digitalWrite(TCS230_S3, HIGH);
red = pulseIn(TCS230_S0, LOW);
green = pulseIn(TCS230_S1, LOW);
digitalWrite(TCS230_S2, HIGH);
digitalWrite(TCS230_S3, HIGH);
blue = pulseIn(TCS230_S0, LOW);
// compare the color values to the predefined RGB values for each color
if (red > RED_R && green < RED_G && blue < RED_B) {
// move servo1 to sort the red object into the corresponding box
servo1.write(45);
delay(1000);
servo1.write(90);
delay(1000);
}
else if (red < GREEN_R && green > GREEN_G && blue < GREEN_B) {
// move servo2 to sort the green object into the corresponding box
servo2.write(45);
delay(1000);
servo2.write(90);
delay(1000);
}
else if (red < BLUE_R && green < BLUE_G && blue > BLUE_B) {
// move servo3 to sort the blue object into the corresponding box
servo3.write(45);
delay(1000);
servo3.write(90);
delay(1000);
}}```

I assume that you're pin variable names match the sensors pin names.
Then your code is utter nonsense. It clearly shows that you have not spent a minute reading any documentation on that sensor.
First of all you never set TCS230_S0, or TCS230_S1 high. So the sensor is turned off. You need to set at least one of those pins high in order to configure the output frequency.
Then you turn S2 low (S1 is still low) and S3 high. This configures the sensor so it outputs the blue value. You then attempt to read red and green pulse width from two output pins.
Then you turn the sensor to output green only and attempt to read blue, again by reading the pulsewidth from an output pin.
First of all you need to turn the sensor to the desired output frequency. Then you need to select a colour you want to measure and then you measure the pulse width of the sensors out pin. S0-S3 are for configuration only.

Related

VGA pixel grouping on STM32

I have some code that displays a single pixel on screen through VGA but am a bit stuck on how I could set multiple pixels on screen where I want them. I set up two Timers for Vertical Sync and Horizontal Sync then using the V-Sync interrupt, I set a flag to allow PA8 to toggle and output a pixel at the correct timing based on the SetCompare value I set on the timer's channel. The STM32f103c8 is also overclocked to 128MHz. Here's the code:
#include "Arduino.h"
//640x480 at 60Hz
static volatile int vflag = 0;
void setup() {
#define FLASH_ACR (*(volatile uint32_t*)(0x40022000))
FLASH_ACR = 0b110010; //enable flash prefetch and wait state to increase stability at higher freq
pinMode(PA0, PWM); //31,468.75Hz (Horizontal Sync) (Channel 1)
Timer2.pause();
Timer2.setOverflow(4067); //reload register value
Timer2.setPrescaleFactor(1); //number that divides main clock
Timer2.setCompare(1, 488); //12% duty cycle (Syncpulse/Wholeline)
Timer2.setCompare(2, 2000); //0-4067 = vertical line going left or right respectively
Timer2.attachInterrupt(2, TRIGGER);
Timer2.refresh();
Timer2.resume();
pinMode(PA6, PWM); //60Hz (Vertical Sync) (Channel 1)
Timer3.pause();
Timer3.setOverflow(4183); //reload register value
Timer3.setPrescaleFactor(510); //number that divides main clock
Timer3.setCompare(1, 16); //0.38% duty cycle (Syncpulse/Wholeframe)
Timer3.setCompare(2, 2000); //0-4183 = horizontal line going up or down respectively
Timer3.attachInterrupt(2, TRIGGER2);
Timer3.refresh();
Timer3.resume();
pinMode(PA8, OUTPUT); //need to set PinMode in order for the ODR register to work
}
void loop() {
}
void TRIGGER(){
if(vflag==1){
__asm__ volatile (
"ldr r0, =(0x4001080C) \n\t" //GPIOA base address is 0x40010800 and ODR offset is 0x0C
"ldr r1, =(1<<8) \n\t" //turn on PA8
"ldr r2, =0 \n\t" //turn off PA8
"str r1, [r0] \n\t" //turn on PA8
"str r2, [r0] \n\t" //turn off PA8
);
vflag = 0; //we set the vflag back to zero when were done outputing pixels.
}
}
I understand there's graphical defects/glitches and the code can be improved on but I'm trying to focus on how in theory this works. What I want to do is have a word display on screen, that word will be made up of letters, and those letters will be made up of groups of pixels. So then whats the best (or simplest) way to group pixels and execute them multiple times on-screen? Or how is this usually done?
I do not code for STM32 so even the code looks foreign to me however it sounds like you are hard-coding the individual pixels with timer... and generating VGA signal by some GPIO. That combination of methods is problematic to use for programmable graphics.
I am using AVR32 (UC3A with much slower clock then yours) to doing VGA image using:
screen buffer (videoram)
simply I have entire screen image stored in MCU memory. So you can simply change it contents without changing the VGA output code ...
The problem is you need to have enough memory for the image (encoded in a way to enable direct transfer to VGA connector). I am using AVR32 with 16+32+32 KByte of RAM but most MCUs have much less RAM (static images can be stored in EPROM but then it would not be possible to change the image output). So in case you do not have enough either lower resolution to fit into memory or add external memory to your system.
use integrated HW peripherial for VGA signal generation
I have more versions of VGA signal generation working:
SDRAM ... using SDRAM interface of the MCU
SMC ... using SMC interface of the MCU
SSC ... using synchronous serial interface
It all boils down to copying the screen buffer to IO interface at the VGA dot clock (~30MHz). Then on HW side combining the used MCU pins into VGA signals
for speed you can use DMA.
On top of all this you need to generate the sync signals and that is all.
So look at your MCU datasheet and find interface capable of synchronous transfer at least 3 bit data (R,G,B) with VGA dot clock speed. The closer the clock is to VGA dot clock the better (as some VGA monitors and LCDs do not tolerate too big difference)
the sync signals can be hardcoded or even encoded in the video ram.
The fastest is to use serial interface but the output is just B&W instead of RGB (unless you got 3 SSC units/channels) however you can send entire 8/16/32 pixels at once or by DMA directly so the MCU has time for other stuff and also requires much less VRAM.
My favourite is SDRAM interface (using just its data bus)
Here image from mine system:
Mine interconnection looks like this (using MCUs SDRAM interface version):
VGA <- AT32UC3A0512
R PX10 (EBI_D0)
G PX09 (EBI_D1)
B PX08 (EBI_D2)
Bright PX07 (EBI_D3)*
HS PA03
VS PA04
Here the relevant source:
VGA_EBI_SDRAMC.h:
//------------------------------------------------------------------------------------------------
#define _PA_VGA_HS 8
#define _PA_VGA_VS 16
#define _PAmo 24
volatile avr32_gpio_port_t *port_PA=&GPIO.port[AVR32_PIN_PA00>>5];
volatile U8 *SDRAM=(U8*)AVR32_EBI_CS0_ADDRESS;
//------------------------------------------------------------------------------------------------
//--- VGA 640x480x4 60Hz -------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
#define VRAM_xs 304
#define VRAM_ys 400
#define VRAM_bs 4
#define VRAM_ls (VRAM_xs>>1)
U8 VRAM[VRAM_ls*VRAM_ys];
U8 VRAM_empty[VRAM_ls];
// Horizontal timing [us]
#define VGA_t0 3
#define VGA_t1 5
#define VGA_t2 32
// Vertikal timing [lines ~31.817us] aby voslo viac bodov tak je to natiahnute na 32us++
#define VGA_ys 525
#define VGA_VS 2
#define VGA_y0 (36+40)
#define VGA_y1 (VGA_y0+VRAM_ys)
//------------------------------------------------------------------------------------------------
void VGA_init();
void VGA_screen();
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
void VGA_init()
{
system_init();
Disable_global_interrupt();
gpio_configure_pins(port_PA,_PAmo,GPIO_DIR_OUTPUT|GPIO_INIT_HIGH);
static const gpio_map_t EBI_GPIO_MAP[] =
{
{ AVR32_EBI_DATA_0_PIN, AVR32_EBI_DATA_0_FUNCTION},
{ AVR32_EBI_DATA_1_PIN, AVR32_EBI_DATA_1_FUNCTION},
{ AVR32_EBI_DATA_2_PIN, AVR32_EBI_DATA_2_FUNCTION},
{ AVR32_EBI_DATA_3_PIN, AVR32_EBI_DATA_3_FUNCTION},
};
gpio_enable_module(EBI_GPIO_MAP, sizeof(EBI_GPIO_MAP) / sizeof(EBI_GPIO_MAP[0]));
AVR32_SDRAMC.mr=0; // normal mode
AVR32_SDRAMC.tr=0; // no refresh (T=0)
AVR32_SDRAMC.cr=
(AVR32_SDRAMC_CR_NC_11_COLUMN_BITS <<AVR32_SDRAMC_CR_NC_OFFSET)
|(AVR32_SDRAMC_CR_NR_13_ROW_BITS <<AVR32_SDRAMC_CR_NR_OFFSET)
|(AVR32_SDRAMC_CR_NB_TWO_BANKS <<AVR32_SDRAMC_CR_NB_OFFSET)
|(AVR32_SDRAMC_CAS_ONE_CYCLE <<AVR32_SDRAMC_CR_CAS_OFFSET)
|(AVR32_SDRAMC_DBW_16_BITS <<AVR32_SDRAMC_CR_DBW_OFFSET)
|(0 <<AVR32_SDRAMC_TWR_OFFSET)
|(0 <<AVR32_SDRAMC_TRC_OFFSET)
|(0 <<AVR32_SDRAMC_TRP_OFFSET)
|(0 <<AVR32_SDRAMC_TRCD_OFFSET)
|(0 <<AVR32_SDRAMC_TRAS_OFFSET)
|(0 <<AVR32_SDRAMC_TXSR_OFFSET);
AVR32_SDRAMC.hsr=AVR32_SDRAMC_HSR_DA_MASK;
AVR32_SDRAMC.mdr=AVR32_SDRAMC_MDR_MD_SDRAM;
// map SDRAM CS -> memory space
AVR32_HMATRIX.sfr[AVR32_EBI_HMATRIX_NR]|=1<<AVR32_EBI_SDRAM_CS;
AVR32_HMATRIX.sfr[AVR32_EBI_HMATRIX_NR];
U32 a;
for (a=0;a<VRAM_ls*VRAM_ys;a++) VRAM[a]=0;
for (a=0;a<VRAM_ls;a++) VRAM_empty[a]=0;
}
//------------------------------------------------------------------------------------------------
void VGA_screen()
{
U32 a,x,y,c,PA,t0;
wait_start(t0);
for (;;)
{
for (PA=_PAmo,a=0,y=0;y<VGA_ys;y++)
{
wait_start(t0);
if (y== 0) PA^=_PA_VGA_VS; else PA^=0; // VS on
if (y==VGA_VS) PA^=_PA_VGA_VS; else PA^=0; // VS off
PA^=_PA_VGA_HS; // HS on
port_PA->ovrc=PA^_PAmo;
port_PA->ovrs=PA;
wait_us(t0,VGA_t0);
PA^=_PA_VGA_HS; // HS off
port_PA->ovrc=PA^_PAmo;
port_PA->ovrs=PA;
wait_us(t0,VGA_t1);
*SDRAM=0; // blank (black)
if ((y>=VGA_y0)&&(y<VGA_y1))
for (x=0;x<VRAM_ls;x++)
{
c=VRAM[a];
*SDRAM=c>>4; // write pixel into SDRAM interface (address is ignored as I use only data bus pins)
a++;
*SDRAM=c; // write pixel into SDRAM interface (address is ignored as I use only data bus pins)
}
*SDRAM=0; // blank (black)
wait_us(t0,VGA_t2);
}
}
}
//------------------------------------------------------------------------------------------------
Main.cpp:
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
#include "System\include.h"
#include "pic_zilog_inside.h"
//#include "VGA_EBI_SMC.h"
#include "VGA_EBI_SDRAMC.h"
//#include "VGA_SSC.h"
//------------------------------------------------------------------------------------------------
void pic_copy(U8 *dst,U32 dst_xs,U32 dst_ys,U32 dst_bs,U8 *src,U32 src_xs,U32 src_ys,U32 src_bs)
{
U32 x0,y0,a0,l0;
U32 x1,y1,a1,l1;
U32 a; U8 c,m;
l0=1; l1=1;
if (dst_bs==1) l0=dst_xs>>3;
if (dst_bs==2) l0=dst_xs>>2;
if (dst_bs==4) l0=dst_xs>>1;
if (dst_bs==8) l0=dst_xs;
if (src_bs==1) l1=src_xs>>3;
if (src_bs==2) l1=src_xs>>2;
if (src_bs==4) l1=src_xs>>1;
if (src_bs==8) l1=src_xs;
for (a0=0;a0<dst_ys*l0;a0++) dst[a0]=0;
for (y0=0;y0<dst_ys;y0++)
{
y1=(y0*(src_ys-1))/(dst_ys-1);
a0=l0*y0;
a1=l1*y1;
for (x0=0;x0<dst_xs;x0++)
{
x1=(x0*(src_xs-1))/(dst_xs-1);
c=0;
if (src_bs==1)
{
c=src[a1+(x1>>3)];
c>>=7-(x1&7);
c&=1;
}
if (src_bs==4)
{
c=src[a1+(x1>>1)];
if (U32(x0&1)==0) c>>=4;
c&=15;
}
if (dst_bs==1)
{
c<<=7-(x0&7);
a=a0+(x0>>3);
dst[a]|=c; if (!c) dst[a]^=c;
}
if (dst_bs==4)
{
if (c) c=15;
if (U32(x0&1)==0) { c<<=4; m=0x0F; } else m=0xF0;
a=a0+(x0>>1);
dst[a]&=m;
dst[a]|=c;
}
}
}
}
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
int main(void)
{
VGA_init();
pic_copy
(
(U8*)VRAM,
VRAM_xs,
VRAM_ys,
VRAM_bs,
(U8*)pic_zilog_inside,
pic_zilog_inside_xs,
pic_zilog_inside_ys,
pic_zilog_inside_bs
);
VGA_screen();
}
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
pic_zilog_inside.h:
const U32 pic_zilog_inside_xs=640;
const U32 pic_zilog_inside_ys=480;
const U32 pic_zilog_inside_bs=1;
const U32 pic_zilog_inside[]= // hard coded image
{
0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
...
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
};
The function pic_copy just copies hard-coded image into VRAM.
The function VGA_screen() creates the VGA signal in endless loop so other tasks must be encoded into ISRs or hard coded into pause code or between individual frames (however this is really demanding on mine setup as I got small MCU clock so there is not much room for other stuff to do). The VRAM is encoded in 16 colors (4 bits per pixel)
8 4 2 1
Brightness B G R
The brightness should just adds some voltage to R,G,B with few resistors and diodes but newer implemented it on HW side instead I have this circuit (8 colors only):
The diodes must be fast with the same barrier voltage and capacitors are 1nF. Its to avoid glitching of the image due to used interface data bus timing. Also the diodes are needed for the brightness if added in future for more info see the R2R current problem in here:
Generating square wave in AVR Assembly without PWM
[Edit1] I made huge changes in code:
//------------------------------------------------------------------------------------------------
//--- VGA EBI SDRAMC DMACA ver: 3.0 --------------------------------------------------------------
//------------------------------------------------------------------------------------------------
/*
VGA <- AT32UC3A3256
R PX10 (EBI_D0)
G PX09 (EBI_D1)
B PX08 (EBI_D2)
Bright PX07 (EBI_D3)*
/HS PX58
/VS PX59
Button PB10 (Bootloader)
debug PX54 (timing of TC00)
*/
//------------------------------------------------------------------------------------------------
//#define _Debug AVR32_PIN_PX54
#define _Button AVR32_PIN_PB10
#define _VGA_HS (1<<(AVR32_PIN_PX58&31))
#define _VGA_VS (1<<(AVR32_PIN_PX59&31))
#define _VGA_mask (_VGA_HS|_VGA_VS)
volatile avr32_gpio_port_t *port_VGA=&GPIO.port[AVR32_PIN_PX58>>5];
volatile U8 *SDRAM=(U8*)AVR32_EBI_CS0_ADDRESS;
//------------------------------------------------------------------------------------------------
//--- VGA 640x480x4 60Hz -------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
#define VRAM_xs 256
#define VRAM_ys 192
#define VRAM_bs 8
#define VRAM_ls ((VRAM_xs*VRAM_bs)>>3)
volatile static U8 VRAM[VRAM_ls*VRAM_ys];
/*------------------------------------------------------------------------------------------------
|------------------------|
| V sync |
| |----------------------|
| | V back |
| | |------------------| |
|H|H| |H|
|s|b| Video 640x480 |f|
|y|a| 525 lines |r|
|n|c| 60 Hz |o|
|c|k| |n|
| | |------------------|t|
| | V front |
|------------------------|
//----------------------------------------------------------------------------------------------*/
// VGA 640x480 60Hz H timing [pixels] dot clock = 25.175MHz
#define VGA_H_front 16
#define VGA_H_sync 96
#define VGA_H_back 48
#define VGA_H_video 640
// VGA 640x480 60Hz H timing [us] Ht = H/25.175, Hf = Vf*(VGA_V_video+VGA_V_front+VGA_V_sync+VGA_V_back)
#define VGA_Ht_front 1
#define VGA_Ht_sync 2
#define VGA_Ht_back 1
#define VGA_Hf 31500
// VGA 640x480 60Hz V timing [lines]
#define VGA_V_video 480
#define VGA_V_front 10
#define VGA_V_sync 2
#define VGA_V_back 33
#define VGA_Vf 60
//------------------------------------------------------------------------------------------------
void VGA_init();
void VGA_screen();
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
__attribute__((__interrupt__)) static void ISR_TC00_VGA() // TC0 chn:0 VGA horizontal frequency
{ // 8us every 31.75us -> 25% of CPU power
tc_read_sr(&AVR32_TC0,0); // more centered image requires +1 us to VGA_Ht_back -> 28% CPU power
#define y0 (VGA_V_video)
#define y1 (y0+VGA_V_front)
#define y2 (y1+VGA_V_sync)
#define y3 (y2+VGA_V_back)
#define yscr0 ((VGA_V_video>>1)-VRAM_ys)
#define yscr1 (yscr0+(VRAM_ys<<1))
static volatile U8 *p;
static volatile U32 y=y3;
#ifdef _Debug
gpio_set_gpio_pin(_Debug);
#endif
// init state
if (y>=y3){ y=0; p=VRAM; port_VGA->ovrs=_VGA_mask; }
// VS sync
if (y==y1) port_VGA->ovrc=_VGA_VS; // VS = L
if (y==y2) port_VGA->ovrs=_VGA_VS; // VS = H
// HS sync
wait_us(VGA_Ht_front); // front
port_VGA->ovrc=_VGA_HS; // HS = L
wait_us(VGA_Ht_sync); // sync
port_VGA->ovrs=_VGA_HS; // HS = H
wait_us(VGA_Ht_back); // back
// 8bit pixelformat DMACA, scan doubler + y offset
if ((y>=yscr0)&&(y<yscr1))
{
// Enable the DMACA
AVR32_DMACA.dmacfgreg = (1 << AVR32_DMACA_DMACFGREG_DMA_EN_OFFSET);
// Src Address: the source_data address
AVR32_DMACA.sar2 = (uint32_t)p;
// Dst Address: the dest_data address
AVR32_DMACA.dar2 = (uint32_t)SDRAM;
// Linked list ptrs: not used.
AVR32_DMACA.llp2 = 0x00000000;
// Channel 2 Ctrl register low
AVR32_DMACA.ctl2l =
(0 << AVR32_DMACA_CTL2L_INT_EN_OFFSET) | // Enable interrupts
(0 << AVR32_DMACA_CTL2L_DST_TR_WIDTH_OFFSET) | // Dst transfer width: 8bit (1,2 znasobi dotclock na 2x)
(0 << AVR32_DMACA_CTL2L_SRC_TR_WIDTH_OFFSET) | // Src transfer width: 8bit
(0 << AVR32_DMACA_CTL2L_DINC_OFFSET) | // Dst address increment: increment
(0 << AVR32_DMACA_CTL2L_SINC_OFFSET) | // Src address increment: increment
(0 << AVR32_DMACA_CTL2L_DST_MSIZE_OFFSET) | // Dst burst transaction len: 1 data items (each of size DST_TR_WIDTH)
(0 << AVR32_DMACA_CTL2L_SRC_MSIZE_OFFSET) | // Src burst transaction len: 1 data items (each of size DST_TR_WIDTH)
(0 << AVR32_DMACA_CTL2L_TT_FC_OFFSET) | // transfer type:M2M, flow controller: DMACA
(1 << AVR32_DMACA_CTL2L_DMS_OFFSET) | // Destination master: HSB master 2
(0 << AVR32_DMACA_CTL2L_SMS_OFFSET) | // Source master: HSB master 1
(0 << AVR32_DMACA_CTL2L_LLP_D_EN_OFFSET) | // Not used
(0 << AVR32_DMACA_CTL2L_LLP_S_EN_OFFSET); // Not used
// Channel 2 Ctrl register high
AVR32_DMACA.ctl2h =
((VRAM_ls) << AVR32_DMACA_CTL2H_BLOCK_TS_OFFSET) | // Block transfer size
(0 << AVR32_DMACA_CTL2H_DONE_OFFSET); // Not done
// Channel 2 Config register low
AVR32_DMACA.cfg2l =
(0 << AVR32_DMACA_CFG2L_HS_SEL_DST_OFFSET) | // Destination handshaking: ignored because the dst is memory
(0 << AVR32_DMACA_CFG2L_HS_SEL_SRC_OFFSET); // Source handshaking: ignored because the src is memory.
// Channel 2 Config register high
AVR32_DMACA.cfg2h =
(0 << AVR32_DMACA_CFG2H_DEST_PER_OFFSET) | // Dest hw handshaking itf: ignored because the dst is memory.
(0 << AVR32_DMACA_CFG2H_SRC_PER_OFFSET); // Source hw handshaking itf: ignored because the src is memory.
// Enable Channel 2 : start the process.
AVR32_DMACA.chenreg = ((4 << AVR32_DMACA_CHENREG_CH_EN_OFFSET) | (4 << AVR32_DMACA_CHENREG_CH_EN_WE_OFFSET));
// DMACA is messing up first BYTE so send it by SW before DMA
*SDRAM=*p;
// scan doubler increment only every second scanline
if ((y&1)==1) p+=VRAM_ls;
}
*SDRAM=0; y++;
#ifdef _Debug
gpio_clr_gpio_pin(_Debug);
#endif
#undef y0
#undef y1
#undef y2
#undef y3
}
//------------------------------------------------------------------------------------------------
void VGA_init()
{
system_init();
Disable_global_interrupt();
gpio_configure_pin(_Button,GPIO_DIR_INPUT);
#ifdef _Debug
gpio_configure_pin(_Debug,GPIO_DIR_OUTPUT);
#endif
gpio_configure_pins(port_VGA,_VGA_mask,GPIO_DIR_OUTPUT|GPIO_INIT_HIGH);
static const gpio_map_t EBI_GPIO_MAP[] =
{
{ AVR32_EBI_DATA_0_PIN, AVR32_EBI_DATA_0_FUNCTION},
{ AVR32_EBI_DATA_1_PIN, AVR32_EBI_DATA_1_FUNCTION},
{ AVR32_EBI_DATA_2_PIN, AVR32_EBI_DATA_2_FUNCTION},
{ AVR32_EBI_DATA_3_PIN, AVR32_EBI_DATA_3_FUNCTION},
};
gpio_enable_module(EBI_GPIO_MAP, sizeof(EBI_GPIO_MAP) / sizeof(EBI_GPIO_MAP[0]));
AVR32_SDRAMC.mr=0; // normal mode
AVR32_SDRAMC.tr=0; // no refresh (T=0)
AVR32_SDRAMC.cr=
(AVR32_SDRAMC_CR_NC_11_COLUMN_BITS <<AVR32_SDRAMC_CR_NC_OFFSET)
|(AVR32_SDRAMC_CR_NR_13_ROW_BITS <<AVR32_SDRAMC_CR_NR_OFFSET)
|(AVR32_SDRAMC_CR_NB_TWO_BANKS <<AVR32_SDRAMC_CR_NB_OFFSET)
|(AVR32_SDRAMC_CAS_ONE_CYCLE <<AVR32_SDRAMC_CR_CAS_OFFSET)
|(AVR32_SDRAMC_DBW_16_BITS <<AVR32_SDRAMC_CR_DBW_OFFSET)
|(0 <<AVR32_SDRAMC_TWR_OFFSET)
|(0 <<AVR32_SDRAMC_TRC_OFFSET)
|(0 <<AVR32_SDRAMC_TRP_OFFSET)
|(0 <<AVR32_SDRAMC_TRCD_OFFSET)
|(0 <<AVR32_SDRAMC_TRAS_OFFSET)
|(0 <<AVR32_SDRAMC_TXSR_OFFSET);
AVR32_SDRAMC.hsr=AVR32_SDRAMC_HSR_DA_MASK;
AVR32_SDRAMC.mdr=AVR32_SDRAMC_MDR_MD_SDRAM;
// map SDRAM CS -> memory space
AVR32_HMATRIX.sfr[AVR32_EBI_HMATRIX_NR]|=1<<AVR32_EBI_SDRAM_CS;
AVR32_HMATRIX.sfr[AVR32_EBI_HMATRIX_NR];
for (U32 a=0;a<VRAM_ls*VRAM_ys;a++) VRAM[a]=0;
timer_init(&AVR32_TC0,0,VGA_Hf,ISR_TC00_VGA,0);
Enable_global_interrupt();
}
//------------------------------------------------------------------------------------------------
Now its enough to call VGA_init(); and the stuff runs in background using Timer and DMA between internal RAM and EBI SDRAM interface. It uses only 25% of CPU power in current configuration. However half of VRAM is wasted as only 4 bits are used so high nibel might be used for back buffering to compensate. I also downclock the stuf to 66MHz as I do not have enough RAM for higher resolutions.

2 DC motors & 1 servo for steering rc car

im working on an RC car project and im using 2 DC motors as a rear wheels ,one servo motor on front for steering with a nano arduino as a microcontroller, HC 06-slave bluetooth receiver, and L298N module for Fwd/Rev and PWM. for my transmitter im using nano arduino a joystick and HC-06 master.
i need my joystick Y axis to drive fwd/rev and X axis for steering. i manged to test the servo alone for X axis steering and it worked, also when tested the code for FWD/REV on Y axis it worked.. however when i combine my code it doesn't work my servo starts shaking and my DC motors start responding to x and y!!
can someone help me pls.
here are the codes im using:
Master code (transmitter);
// == MASTER DEVICE - Joystick ==
//int xAxis, yAxis;
void setup() {
Serial.begin(9600); // Default communication rate of the Bluetooth
module
}
void loop() {
xAxis = analogRead(A0); // Read Joysticks X-axis
yAxis = analogRead(A1); // Read Joysticks Y-axis
// Send the values via the serial port to the slave HC-05 Bluetooth
device
Serial.write(xAxis/4); // Dividing by 4 for converting from 0 -
1023 to 0 - 256, (1 byte) range
Serial.write(yAxis/4);
delay(20);
}
slave code (servo only);
#include <Servo.h>
Servo myServo;
int yAxis;
void setup() {
myServo.attach(3);
Serial.begin(9600); // Default communication rate of the Bluetooth
module
}
void loop() {
yAxis = 510 / 4;
// Read the incoming data from the Joystick, or the master
Bluetooth device
if(Serial.available() > 0){ // Checks whether data is comming from
the serial port
yAxis = Serial.read(); // Reads the data from the serial port
}
delay(10);
myServo.write(yAxis);
delay(10);
}
slave code for DC motors FWD/REV;
#include <Servo.h>
#define enA 9
#define in1 4
#define in2 5
#define enB 10
#define in3 6
#define in4 7
//int servoPin = 3;
int xAxis;
unsigned int x = 0;
unsigned int y = 0;
int motorSpeedA = 0;
int motorSpeedB = 0;
//Servo Servo1;
void setup() {
pinMode(enA, OUTPUT);
pinMode(enB, OUTPUT);
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
pinMode(in3, OUTPUT);
pinMode(in4, OUTPUT);
Serial.begin(9600); // Default communication rate of the Bluetooth module
// Servo1.attach(servoPin);
}
void loop() {
// Default value - no movement when the Joystick stays in the center
x = 510 / 4;
y = 510 / 4;
// Read the incoming data from the Joystick, or the master Bluetooth device
while (Serial.available() >= 2) {
x = Serial.read();
// delay(10);
// y = Serial.read();
}
delay(10);
// Convert back the 0 - 255 range to 0 - 1023, suitable for motor control code below
xAxis = x*4;
// yAxis = y*4;
// Y-axis used for forward and backward control
if (xAxis < 470) {
// Set Motor A backward
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
// Set Motor B backward
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
// Convert the declining Y-axis readings for going backward from 470 to 0 into 0 to 255 value for the PWM signal for increasing the motor speed
motorSpeedA = map(xAxis, 470, 0, 0, 255);
motorSpeedB = map(xAxis, 470, 0, 0, 255);
}
else if (xAxis > 550) {
// Set Motor A forward
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
// Set Motor B forward
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);
// Convert the increasing Y-axis readings for going forward from 550 to 1023 into 0 to 255 value for the PWM signal for increasing the motor speed
motorSpeedA = map(xAxis, 550, 1023, 0, 255);
motorSpeedB = map(xAxis, 550, 1023, 0, 255);
}
// If joystick stays in middle the motors are not moving
else {
motorSpeedA = 0;
motorSpeedB = 0;
}
if (motorSpeedA < 70) {
motorSpeedA = 0;
}
if (motorSpeedB < 70) {
motorSpeedB = 0;
}
analogWrite(enA, motorSpeedA); // Send PWM signal to motor A
analogWrite(enB, motorSpeedB); // Send PWM signal to motor B
}
i want to combine them so one of the axis is for DC motors FWD/REV and the other axis is for servo motor right/left.
You must be more explicit with the data you send.
Don't send x=20,y=30 as char[2]={20,30}.
A minimum would be char[4]={'x',20,'y',30}.
Then you will check that you receive complete datagram of 4 char, and then you can check that you don't confuse x with y.

Change servo angle based on Bluetooth input

I'm using an app to either turn on an LED or change the angle of a micro servo depending on which button is pressed (using Arduino). My code works for the LED (while the button is pressed, the LED is on) but nothing happens when I press the button meant to change the angle of the servo to 40.
// Bluetooth serial:
#include <SoftwareSerial.h> // import the serial library
// setup the bluetooth coms
SoftwareSerial BTSerial(8,7);
#include <Servo.h>
int servoPin = 0;
Servo servo;
int angle = 0; // servo position in degrees
int input = 0;
int led2 = 13;
void setup() {
// put your setup code here, to run once:
servo.attach(servoPin);
Serial.begin(9600); // coms w/ computer
BTSerial.begin(9600); // coms w/ Bluetooth
pinMode(led2, OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
if (BTSerial.available())
{
input = BTSerial.read();
digitalWrite(led2, LOW);
switch(input) {
case 'E':
angle = 40;
break;
case 'C':
digitalWrite(led2, HIGH);
break;
}
servo.write(angle);
}
}
The input is right as I checked by also turning the LED on in case 'E' where it worked as normal. I had also tried using servo.write() within the case function as well but this didn't work either.
case 'E':
servo.write(40);
break;
You cannot use digital pins 0 or 1 as input:
As mentioned, those are serial send and receive pins. If you power your computer through USB, it can interfere if you try to use them, since it's reading from both the USB to Serial and the pin. Also you have an issue with anything connected (well, not anything, but remove it just to be safe) when you're trying to program. If you use the pins as intended, and program then run it off battery, it should be no problem at all.
Most of us stay away from it because it's a bit of a hassle
Depending on your Arduino model, servo.attach only supports pins 9 and 10:
Note that in Arduino 0016 and earlier, the Servo library supports only servos on only two pins: 9 and 10.
Or you could just use one of those anyway.

Serial monitor constantly say 0 when using arduino and sound sensor

I am having trouble with the arduino sound sensor and LEDs. I keep on getting the value of 0 in my serial monitor, the same thing happens with another sound sensor that I have. I am currently trying to make it light up the LEDs based on the sound but with the serial monitor reading 0 it will not activate the code. There should be a picture attached. The lights on the sound sensor is lighting up so I know the GND and 5V is working. Since it is hard to tell I am using 330 ohm resisters. I got the sound sensor from an elegoo starter kit, so I know it might be cheap. The picture is in the link at the end. Thank you.
int MicPin = A0;
int MicValue1 = 0;
int MicValue2 = 0;
int led1 = 2;
int led2 = 4;
int led3 = 6;
int led4 = 8;
void setup() {
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
pinMode(MicPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
MicValue1 = analogRead(MicPin);
Serial.println(MicValue1);
delay(1);
MicValue2 = analogRead(MicPin);
Serial.println(MicValue2);
if (MicValue1 - MicValue2 > 1) {
digitalWrite(led1, HIGH);
delay(2000);
}
else {
digitalWrite(led1, LOW);
}
}
enter image description here
I assume that you have a simple analog-output sensor module that provides 10bit analog values based on the environment volume level. If this assumption is correct, you wired all pins correctly and the received value is always out of range or at the maximum, you maybe had to integrate a resistor to get a valid value. Try a small resistor and increase the resistance until you receive suitable values. Maybe the documentation of your module provides further information.
There is a small rotating knob connected to the sensor on which we need to rotate to adjust particular resistance values, you can see different values in serial monitor out.
Useful link

Using RGB Lights with Arduino Struct

I am attempting to use a struct with Arduino to turn on multiple RGB LEDs to specific colors. With this sample code, I created a struct to hold a red pin num, a blue pin num, a blue value, and a red value. I am only using two of the 3 pins on the LED since I only need the colors red, blue, and purple for my application. When I run this code, the incorrect light turns on and in the incorrect color. I am not sure if I correctly understand how to use a struct in the Arduino environment. I used this source http://playground.arduino.cc/Code/Struct to find the basic syntax for a struct in Arduino. I am using it similar to how one might use an object in OOP. I am looking for clarity as to how to use the struct in Arduino and specifically I am not able to get the expected result. I expect for the LED that is connected to pin3 and pin4 to light up purple (as its red and blue pins are both set to HIGH) but instead the LED connected to pin1 and pin2 will light up red (as if pin1 is set to HIGH). Moreover, when I remove the print statements nothing turns on at all (even though this is the only change made). I have checked my wiring countless times and have determined that it is not a hardware issue. Thank you for any help that you can provide.
struct light {
int redPin ;
int bluePin;
int redValue;
int blueValue;
};
light light1;
void setup() {
Serial.begin(9600);
pinMode(light1.redPin, OUTPUT);
pinMode(light1.bluePin, OUTPUT);
light1.redPin = 3;
light1.bluePin = 4;
light1.redValue = HIGH;
light1.blueValue = HIGH;
}
void loop() {
Serial.print(light1.redPin);
Serial.println(light1.redValue);
Serial.print(light1.bluePin);
Serial.println(light1.blueValue);
digitalWrite(light1.redPin, light1.redValue);
digitalWrite(light1.bluePin, light1.blueValue);
}
As Pawel suggested, you are doing things in the wrong order. This would make a lot more sense:
light1.redPin = 3;
light1.bluePin = 4;
light1.redValue = HIGH;
light1.blueValue = HIGH;
pinMode(light1.redPin, OUTPUT);
pinMode(light1.bluePin, OUTPUT);
I am not sure if I correctly understand how to use a struct in the Arduino environment.
It is exactly the same as in C++.
but instead the LED connected to pin1 and pin2 will light up red (as if pin1 is set to HIGH)
Your serial prints will set pin D1 (Tx) to an output and you are seeing your serial prints as turning on the pins.
when I remove the print statements nothing turns on at all
As expected, as you are not sending data to those pins.
The default for an uninitialized global variable is zero, so I would expect that you have set pin D0 (the first pin, labelled Rx) to be an output, and then you are writing to it.
(Edited to add)
Actually, once you have done a Serial.begin the serial hardware takes over pins 0 and 1, and thus attempts to write to them fail.
The output you see on pin D1 is the Serial.print as I mentioned before, and the output on pin D0 is just the internal pull-up used to keep Rx high in the event that you are not using it just now. If you plug in an LED you will see that D0 is duller than D1.

Resources