Finally servo
This commit is contained in:
parent
6d4167809b
commit
70c2fe56c8
28
src/components/forms/Slider.tsx
Normal file
28
src/components/forms/Slider.tsx
Normal file
@ -0,0 +1,28 @@
|
||||
import { ChangeEventHandler } from "react";
|
||||
|
||||
interface SliderProps {
|
||||
className?: string;
|
||||
name?: string;
|
||||
value?: number;
|
||||
onChange?: ChangeEventHandler<HTMLInputElement | null>
|
||||
}
|
||||
|
||||
export function Slider ({ className, name, value, onChange }: SliderProps) {
|
||||
const percent = value ? value/10 : 0
|
||||
|
||||
return (
|
||||
<input
|
||||
className={`slider ${className}`}
|
||||
style={{
|
||||
background: `linear-gradient(to right, #3a3affcc ${percent}%, #3a3aff4d ${percent}%)`
|
||||
}}
|
||||
type="range"
|
||||
min={0}
|
||||
max={1000}
|
||||
name={name}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
id=""
|
||||
/>
|
||||
)
|
||||
}
|
@ -10,10 +10,10 @@ import Button from "../forms/Button";
|
||||
function Card ({ index, resistor }: { index: number, resistor: DynamicPinState }) {
|
||||
const { setResistorPin, removeResistor } = usePhotoresistor();
|
||||
|
||||
const [isListen, setListen] = useState(false);
|
||||
const [isListen, setListen] = useState<boolean>(false);
|
||||
|
||||
const resistance = resistor.state;
|
||||
const intensity = `${resistor.state / 1023 * 100}%`;
|
||||
const resistance: number = Math.floor(resistor.state);
|
||||
const intensity: number = Math.floor(100 - (resistor.state / 1023 * 100));
|
||||
|
||||
const toggleListen = () => {
|
||||
setListen(!isListen);
|
||||
@ -46,7 +46,7 @@ function Card ({ index, resistor }: { index: number, resistor: DynamicPinState }
|
||||
/>
|
||||
<TwoRowTab
|
||||
prop="Light Intensity"
|
||||
value={intensity}
|
||||
value={`${intensity}%`}
|
||||
/>
|
||||
<EvoInput
|
||||
className="h-10"
|
||||
|
122
src/components/landing/ControlServo.tsx
Normal file
122
src/components/landing/ControlServo.tsx
Normal file
@ -0,0 +1,122 @@
|
||||
import { ChangeEvent, MouseEventHandler, Ref, useEffect, useState } from "react";
|
||||
import { useServo } from "../../hooks";
|
||||
import { DynamicPinState } from "../../types/board";
|
||||
import EvoInput from "../forms/EvoInput";
|
||||
import Button from "../forms/Button";
|
||||
import { Slider } from "../forms/Slider";
|
||||
|
||||
|
||||
function Bar ({ index, servo }: { index: number, servo: DynamicPinState }) {
|
||||
const { setServoPin, setDegree, removeServo } = useServo();
|
||||
|
||||
const [percentage, setPercent] = useState(0);
|
||||
const [isListen, setListen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const deg = Math.floor((percentage / 1000) * 180);
|
||||
setDegree(servo.pin, deg);
|
||||
}, [percentage]);
|
||||
|
||||
const toggleListen = () => {
|
||||
setListen(!isListen);
|
||||
}
|
||||
|
||||
const handleChange = (e: ChangeEvent<HTMLInputElement | null>) => {
|
||||
const percent = Number.parseInt(e.target.value);
|
||||
if (!Number.isNaN(percent)) setPercent(percent);
|
||||
}
|
||||
|
||||
const handleChangePin = (e: ChangeEvent<HTMLInputElement | null>) => {
|
||||
setServoPin(index, e.target.value);
|
||||
}
|
||||
|
||||
const handleDelete = () => {
|
||||
removeServo(index);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="border border-border bg-secondary rounded-lg p-6 animate-size-fade-in relative">
|
||||
<button className="ms-auto absolute -right-24 top-1/2 -translate-y-1/2 bg-finn hover:bg-secondary transition border border-border rounded-lg px-5" onClick={handleDelete}>
|
||||
<i className="bi bi-dash text-3xl"></i>
|
||||
</button>
|
||||
<div className="flex justify-between mb-8">
|
||||
<div className="flex gap-3">
|
||||
<EvoInput
|
||||
name="Pin"
|
||||
value={servo.pin.toString()}
|
||||
onChange={handleChangePin}
|
||||
type="text"
|
||||
/>
|
||||
{!isListen ? (
|
||||
<Button.Primary onClick={toggleListen} className="text-sm !py-0 h-11">Start Listening</Button.Primary>
|
||||
) : (
|
||||
<Button.Danger onClick={toggleListen} className="text-sm !py-0 h-11">Stop Listening</Button.Danger>
|
||||
)}
|
||||
</div>
|
||||
<div className="">{servo.state+"°"}</div>
|
||||
</div>
|
||||
<div className="">
|
||||
<Slider
|
||||
name={`Servo ${servo.pin}`}
|
||||
value={percentage}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function BarPlus ({ onClick }: { onClick?: MouseEventHandler<HTMLButtonElement> }) {
|
||||
return (
|
||||
<button
|
||||
className="bg-finn h-36 hover:bg-secondary transition col-span-2 rounded-lg border border-border flex items-center justify-center"
|
||||
onClick={onClick}
|
||||
>
|
||||
<i className="bi bi-plus text-6xl text-border"></i>
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
function ControlServo ({ refto }: { refto?: Ref<HTMLDivElement> }) {
|
||||
const { motoServo, addServo } = useServo();
|
||||
|
||||
const handleAdd = (): void => {
|
||||
let anopin = 5;
|
||||
for (let i = 0; i < motoServo.length; i++) {
|
||||
if (motoServo.filter(servo => (servo.pin == `A${anopin}` || servo.pin == anopin)).length > 0) {
|
||||
anopin--;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
addServo(`A${anopin}`, 0);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="container py-16" id="rgb-led" ref={refto}>
|
||||
<div className="container-grid items-center relative">
|
||||
<div className={`col-span-8`}>
|
||||
<h2 className="text-4xl font-poppins font-bold leading-normal mb-4">
|
||||
Servo
|
||||
</h2>
|
||||
<div className="grid grid-cols-8 mb-8">
|
||||
<p className="col-span-6">Servo motors is a type of electric motor designed to provide precise motion and accurate control. Servo motors use a feedback mechanism to control their shaft position and rotational speed.</p>
|
||||
</div>
|
||||
<div className={`flex flex-col gap-6`}>
|
||||
{motoServo.map((servo, i) => (
|
||||
<Bar
|
||||
key={i}
|
||||
servo={servo}
|
||||
index={i}
|
||||
/>
|
||||
))}
|
||||
{motoServo.length < 6 && <BarPlus
|
||||
onClick={handleAdd}
|
||||
/>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ControlServo;
|
@ -46,7 +46,12 @@ const INIT_VALUES: ControllerContextProps = {
|
||||
state: 127
|
||||
}
|
||||
],
|
||||
motoServo: [],
|
||||
motoServo: [
|
||||
{
|
||||
pin: "A0",
|
||||
state: 0
|
||||
}
|
||||
],
|
||||
photoresistor: [
|
||||
{
|
||||
pin: "A0",
|
||||
|
@ -58,30 +58,56 @@
|
||||
@apply grid grid-cols-8 gap-6;
|
||||
}
|
||||
|
||||
|
||||
.switch {
|
||||
@apply rounded-lg transition;
|
||||
}
|
||||
.switch > .handler {
|
||||
@apply rounded-md p-[6px] transition-[margin];
|
||||
}
|
||||
@layer components {
|
||||
.slider {
|
||||
-webkit-appearance: none;
|
||||
-webkit-transition: .15s;
|
||||
color: #3a3affcc;
|
||||
color: #3a3aff4d;
|
||||
@apply appearance-none rounded-full w-full h-3 bg-primary bg-opacity-30 transition;
|
||||
}
|
||||
.slider::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
@apply appearance-none transition-all rounded-full w-5 h-5 bg-primary cursor-pointer;
|
||||
}
|
||||
.slider::-webkit-slider-thumb:hover {
|
||||
-webkit-appearance: none;
|
||||
box-shadow: 0 0 0 8px #3838ff66;
|
||||
}
|
||||
.slider::-webkit-slider-thumb:active {
|
||||
-webkit-appearance: none;
|
||||
box-shadow: 0 0 0 12px #3838ff66;
|
||||
@apply w-6 h-6;
|
||||
}
|
||||
.slider::-moz-range-thumb {
|
||||
@apply w-5 h-5 bg-primary cursor-pointer;
|
||||
}
|
||||
|
||||
|
||||
.btn {
|
||||
@apply px-5 py-4 transition font-roboto-mono rounded-lg
|
||||
}
|
||||
|
||||
|
||||
.switch-on {
|
||||
@apply border-primary bg-primary bg-opacity-40;
|
||||
}
|
||||
.switch-on > .handler {
|
||||
@apply bg-primary ms-[50%];
|
||||
}
|
||||
|
||||
.switch-off {
|
||||
@apply border-disabled bg-transparent;
|
||||
}
|
||||
.switch-off > .handler {
|
||||
@apply bg-disabled ms-0;
|
||||
.btn {
|
||||
@apply px-5 py-4 transition font-roboto-mono rounded-lg
|
||||
}
|
||||
|
||||
|
||||
.switch {
|
||||
@apply rounded-lg transition;
|
||||
}
|
||||
.switch > .handler {
|
||||
@apply rounded-md p-[6px] transition-[margin];
|
||||
}
|
||||
|
||||
.switch-on {
|
||||
@apply border-primary bg-primary bg-opacity-40;
|
||||
}
|
||||
.switch-on > .handler {
|
||||
@apply bg-primary ms-[50%];
|
||||
}
|
||||
|
||||
.switch-off {
|
||||
@apply border-disabled bg-transparent;
|
||||
}
|
||||
.switch-off > .handler {
|
||||
@apply bg-disabled ms-0;
|
||||
}
|
||||
}
|
@ -121,6 +121,43 @@ export function usePiezo () {
|
||||
|
||||
|
||||
|
||||
export function useServo () {
|
||||
const { motoServo, setMotoServo } = useContext(BoardControllerContext);
|
||||
|
||||
const getServo = (pin: number | string) => {
|
||||
return motoServo.find(val => val.pin == pin);
|
||||
}
|
||||
|
||||
const addServo = (pin: number | string, state: number) => {
|
||||
const newPesistor = [...motoServo, { pin, state }];
|
||||
setMotoServo!(newPesistor);
|
||||
}
|
||||
|
||||
const removeServo = (index: number) => {
|
||||
const newPesistor = motoServo.filter((_servo, i) => i != index);
|
||||
setMotoServo!(newPesistor);
|
||||
}
|
||||
|
||||
const setDegree = (pin: number | string, state: number) => {
|
||||
const newPiezo = motoServo.map(servo => {
|
||||
if (servo.pin == pin) return { pin, state };
|
||||
return servo;
|
||||
})
|
||||
setMotoServo!(newPiezo);
|
||||
}
|
||||
|
||||
const setServoPin = (index: number, newPin: number | string) => {
|
||||
const newPesistor = motoServo.map((servo, i) => {
|
||||
if (i == index) return { pin: newPin, state: servo.state };
|
||||
return servo;
|
||||
})
|
||||
setMotoServo!(newPesistor);
|
||||
}
|
||||
|
||||
return { motoServo, getServo, addServo, removeServo, setDegree, setServoPin };
|
||||
}
|
||||
|
||||
|
||||
export function usePhotoresistor () {
|
||||
const { photoresistor, setPhotoresistor } = useContext(BoardControllerContext);
|
||||
|
||||
@ -147,4 +184,4 @@ export function usePhotoresistor () {
|
||||
}
|
||||
|
||||
return { photoresistor, getResistor, addResistor, removeResistor, setResistorPin };
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import ControlNav from "../data/control-navigation.json";
|
||||
import ControlRgbLed from "../components/landing/ControlRgbLed";
|
||||
import ControlPiezo from "../components/landing/ControlPiezo";
|
||||
import ControlPhotoresistor from "../components/landing/ControlPhotoresistor";
|
||||
import ControlServo from "../components/landing/ControlServo";
|
||||
|
||||
function MainPage () {
|
||||
const led = useRef<HTMLDivElement | null>(null);
|
||||
@ -27,6 +28,7 @@ function MainPage () {
|
||||
<ControlLED refto={led} />
|
||||
<ControlRgbLed refto={rgbLed} />
|
||||
<ControlPiezo refto={piezo} />
|
||||
<ControlServo />
|
||||
<ControlPhotoresistor />
|
||||
</MainBody>
|
||||
</>)
|
||||
|
Loading…
x
Reference in New Issue
Block a user