<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>네 말이 옳다</title>
    <link>https://he823.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Mon, 1 Jun 2026 19:53:44 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>네 말이 옳다</managingEditor>
    <item>
      <title>#4 SITL 환경에서 ROS Camera Topic을 이용해 Aruco Marker 검출하기</title>
      <link>https://he823.tistory.com/13</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Aruco Marker는 검은색 테두리와 내부 이진 행렬로 구성된 정사각형 마커입니다.&lt;br /&gt;로봇분야에서 많이 사용되며 다양한 크기로 QR코드 같은 패턴이 있어 각각의 패턴엔 ID가 할당되어 식별될 수 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;414&quot; data-origin-height=&quot;350&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Sfl0u/dJMcaaFc576/7SY1NJi7G7BoBx165AFMP0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Sfl0u/dJMcaaFc576/7SY1NJi7G7BoBx165AFMP0/img.jpg&quot; data-alt=&quot;Aruco Marker&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Sfl0u/dJMcaaFc576/7SY1NJi7G7BoBx165AFMP0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSfl0u%2FdJMcaaFc576%2F7SY1NJi7G7BoBx165AFMP0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;414&quot; height=&quot;350&quot; data-origin-width=&quot;414&quot; data-origin-height=&quot;350&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Aruco Marker&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 Aruco Marker를 이용해 카메라의 위치를 추적하고, 물체의 위치를 추적할 수 있습니다.&lt;br /&gt;이번엔, PX4 Gazebo-Classic 환경에서 Aruco Marker를 추가하고, 인식해 보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;환경&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;Ubuntu 20.04&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;ROS1 noetic&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;PX4 1.15.0&lt;/span&gt;&lt;br /&gt;&lt;span&gt;ros-noetic-mavros &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;.20.1&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. PX4 시뮬레이션 환경에 Aruco Marker를 추가하기&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1777983976377&quot; class=&quot;bash&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;cd ~/PX4-Autopilot

source /opt/ros/noetic/setup.bash
source Tools/simulation/gazebo-classic/setup_gazebo.bash $(pwd) $(pwd)/build/px4_sitl_default
export ROS_PACKAGE_PATH=$ROS_PACKAGE_PATH:$(pwd)
export ROS_PACKAGE_PATH=$ROS_PACKAGE_PATH:$(pwd)/Tools/simulation/gazebo-classic/sitl_gazebo-classic

roslaunch px4 posix_sitl.launch \
  vehicle:=iris_downward_depth_camera \
  world:=$(pwd)/Tools/simulation/gazebo-classic/sitl_gazebo-classic/worlds/iris_irlock.world&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PX4는 ROS Gazebo시뮬레이션을 지원합니다. &lt;br /&gt;또한 World와 Model을 선택하여 실행할 수 있습니다.&lt;br /&gt;이번에는 iris_downward_depth_camera를 사용하겠습니다.&lt;br /&gt;Gazebo Classic 시뮬레이션에 iris_irlock.world에는 id0의 4x4 Aruco Marker가 0.0에 위치해 있습니다. &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&lt;a href=&quot;https://he823.tistory.com/6&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&quot;#0 PX4 개발환경 구성&quot;&lt;/a&gt;에서 UDP로 카메라 스트리밍을 해본 &lt;span style=&quot;background-color: #fafafa; color: #383a42; text-align: start;&quot;&gt;typhoon_h480 모델과는&lt;/span&gt; 다르게 &lt;br /&gt;iris_downward는 rostopic의 형태로 카메라가 스트리밍 됩니다.&lt;br /&gt;그래서 시뮬레이션 할 때는 roslaunch를 이용해 모델을 열어야지 정상적으로 Camera Topic이 발행됩니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. Camera Topic을 이용해 Aruco Marker 검출&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1779634308266&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#!/usr/bin/env python3
import cv2
import rospy
from cv_bridge import CvBridge, CvBridgeError
from sensor_msgs.msg import Image


class ArucoViewerNode:
    def __init__(self):
        self.bridge = CvBridge()

        self.image_topic = rospy.get_param(&quot;~image_topic&quot;, &quot;/camera/rgb/image_raw&quot;)
        self.dictionary_name = rospy.get_param(&quot;~dictionary&quot;, &quot;DICT_4X4_50&quot;)

        self.dictionary = self._load_dictionary(self.dictionary_name)
        self.parameters = cv2.aruco.DetectorParameters_create()

        self.image_sub = rospy.Subscriber(
            self.image_topic,
            Image,
            self.image_callback,
            queue_size=1,
            buff_size=2**24
        )

        rospy.loginfo(&quot;ArUco viewer subscribed to %s&quot;, self.image_topic)

    def _load_dictionary(self, name):
        if not hasattr(cv2, &quot;aruco&quot;):
            raise RuntimeError(&quot;cv2.aruco is not available&quot;)

        dictionary_id = getattr(cv2.aruco, name)
        return cv2.aruco.getPredefinedDictionary(dictionary_id)

    def image_callback(self, msg):
        try:
            frame = self.bridge.imgmsg_to_cv2(msg, desired_encoding=&quot;bgr8&quot;)
        except CvBridgeError as exc:
            rospy.logwarn(&quot;cv_bridge conversion failed: %s&quot;, exc)
            return

        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

        corners, ids, rejected = cv2.aruco.detectMarkers(
            gray,
            self.dictionary,
            parameters=self.parameters
        )

        if ids is not None:
            cv2.aruco.drawDetectedMarkers(frame, corners, ids)

        cv2.imshow(&quot;ArUco Marker Detection&quot;, frame)
        cv2.waitKey(1)


def main():
    rospy.init_node(&quot;aruco_viewer&quot;)
    ArucoViewerNode()
    rospy.spin()
    cv2.destroyAllWindows()


if __name__ == &quot;__main__&quot;:
    main()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fafafa; color: #333333; text-align: start;&quot;&gt;대략적인 프로세스는&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #fafafa; color: #333333; text-align: start;&quot;&gt;Camera Image Topic 수신 -&amp;gt;&lt;br /&gt;OpenCV를 이용해 이미지 변환 -&amp;gt; &lt;br /&gt;흑백변환 -&amp;gt;&lt;br /&gt;Aruco Marker 검출&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #fafafa; color: #333333; text-align: start;&quot;&gt;입니다.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;1150&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kzZH1/dJMcaiQIiDr/AoiskI51asmD0WQCbAunZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kzZH1/dJMcaiQIiDr/AoiskI51asmD0WQCbAunZK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kzZH1/dJMcaiQIiDr/AoiskI51asmD0WQCbAunZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkzZH1%2FdJMcaiQIiDr%2FAoiskI51asmD0WQCbAunZK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2048&quot; height=&quot;1150&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;1150&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fafafa; color: #333333; text-align: start;&quot;&gt;&lt;br /&gt;정상적으로 Marker가 인식되는 모습을 확인할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 style=&quot;color: #ffffff; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;</description>
      <category>드론/PX4</category>
      <category>aruco marker</category>
      <category>Gazebo-Classic</category>
      <category>opencv</category>
      <author>네 말이 옳다</author>
      <guid isPermaLink="true">https://he823.tistory.com/13</guid>
      <comments>https://he823.tistory.com/13#entry13comment</comments>
      <pubDate>Sun, 24 May 2026 23:30:02 +0900</pubDate>
    </item>
    <item>
      <title>#3 uXRCE-DDS와 ROS2를 활용한 드론 경로 가시화</title>
      <link>https://he823.tistory.com/12</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이전 게시글에서는 MAVlink Router를 이용해 Endpoint에서 MAVlink 데이터를 주고받는 방법에 대해 알아봤습니다.&lt;br /&gt;이번에는, MAVlink 데이터를 ROS 토픽처럼 볼 수 있는 uXRCE-DDS에 대해 알아보고 드론의 MAVlink 데이터를 ROS2 토픽으로 변환해 이를 Rviz로 가시화해보겠습니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;환경&lt;/b&gt;&lt;br /&gt;Ubuntu 20.04&lt;br /&gt;ROS2 Foxy&lt;br /&gt;PX4 1.15.0&lt;br /&gt;uXRCE-DDS 2.4.3&lt;br /&gt;px4_msgs 1.15&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. uXRCE-DDS&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PX4는 MAVlink 데이터를 통해 드론의 상태를 알릴 수 있고, 명령과 제어가 가능합니다.&lt;br /&gt;가만히 살펴보면, MAVlink의 데이터 통신 방식은 ROS에서 데이터 통신방식과 개념이 비슷합니다.&lt;br /&gt;&lt;br /&gt;MAVlink uORB 메시지를 마치&amp;nbsp; ROS의 Topic처럼 Publish 하고 Subscribe 할 수 있도록 하는 프로토콜이 uXRCE-DDS입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1015&quot; data-origin-height=&quot;386&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xPefT/dJMcaa6e8BV/kMT2wURF8Dc3V1jdzSoZ2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xPefT/dJMcaa6e8BV/kMT2wURF8Dc3V1jdzSoZ2k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xPefT/dJMcaa6e8BV/kMT2wURF8Dc3V1jdzSoZ2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxPefT%2FdJMcaa6e8BV%2FkMT2wURF8Dc3V1jdzSoZ2k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1015&quot; height=&quot;386&quot; data-origin-width=&quot;1015&quot; data-origin-height=&quot;386&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Client는 기본적으로 PX4 펌웨어에 포함되어 있으므로 Agent를 실행하여 Topic처럼 볼 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;설치&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1777814129482&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git clone -b v2.4.3 https://github.com/eProsima/Micro-XRCE-DDS-Agent.git
cd Micro-XRCE-DDS-Agent
mkdir build
cd build
cmake ..
make
sudo make install
sudo ldconfig /usr/local/lib/&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치가 완료되면, Gazebo와 XRCE-DDS를 실행해 ROS2 Topic이 발행되는 모습을 확인해 봅시다.&lt;/p&gt;
&lt;pre id=&quot;code_1777814295758&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#터미널 1
MicroXRCEAgent udp4 -p 8888&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1777814353191&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#터미널2
cd ~/PX4-Autopilot
make px4_sitl gazebo-classic&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1777814370556&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#터미널3
ros2 topic list&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2560&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dH4ueb/dJMcadhAasD/qIOmz5020Ay7EXMrBWEKe1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dH4ueb/dJMcadhAasD/qIOmz5020Ay7EXMrBWEKe1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dH4ueb/dJMcadhAasD/qIOmz5020Ay7EXMrBWEKe1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdH4ueb%2FdJMcadhAasD%2FqIOmz5020Ay7EXMrBWEKe1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2560&quot; height=&quot;1600&quot; data-origin-width=&quot;2560&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;fmu/in&lt;br /&gt;fmu/out으로 ROS2 Topic이 발행되고 있는 모습을 확인할 수 있습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. ROS2를 활용한 드론 경로 가시화&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단하게, ROS2 토픽으로 변환된 MAVlink 데이터를 Subscribe 하고 데이터를 가공해 드론의 경로를 가시화해봅시다.&lt;br /&gt;&lt;br /&gt;PX4에 ROS2를 이용하려면 메시지 정의가 이루어져야 합니다.&lt;br /&gt;ROS2 노드와 PX4 구성요소들을 연결하기 위해서 px4_msgs를 사용합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1777815226712&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#ros2 workspace 생성
mkdir ros_workspace
cd ros_workspace

#px4_msgs v1.15 소스코드 가져오기 
git clone https://github.com/PX4/px4_msgs.git
cd px4_msgs
git checkout release/1.15
cd ..

#의존성 설치 및 빌드
rosdep update
rosdep install --from-paths src --ignore-src -y
colcon build --packages-select px4_msgs --symlink-install

#이후 환경 설정 로드
source install/setup.bash&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1777815670135&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd ~/ros_workspace/src

#패키지 생성
ros2 pkg create --build-type ament_python drone_viz_pkg --dependencies rclpy px4_msgs geometry_msgs nav_msgs
cd ~/ros_workspace/src/drone_viz_pkg/drone_viz_pkg/
nano trajectory_node.py&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 프로그램을 작성합니다.&lt;br /&gt;&lt;br /&gt;이때, px4는 NED좌표계를 사용하고, Rviz는 ENU좌표계를 사용하므로 드론의 위치를 적절히 변환하여 입력하도록 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1777815730551&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import rclpy
from rclpy.node import Node
from rclpy.qos import QoSProfile, ReliabilityPolicy, HistoryPolicy, DurabilityPolicy
from px4_msgs.msg import VehicleLocalPosition
from geometry_msgs.msg import PoseStamped
from nav_msgs.msg import Path

class DroneTrajectoryVisualizer(Node):
    def __init__(self):
        super().__init__('drone_trajectory_visualizer')

        qos_profile = QoSProfile(
            reliability=ReliabilityPolicy.BEST_EFFORT,
            durability=DurabilityPolicy.TRANSIENT_LOCAL,
            history=HistoryPolicy.KEEP_LAST,
            depth=1
        )

        self.subscription = self.create_subscription(
            VehicleLocalPosition,
            '/fmu/out/vehicle_local_position',
            self.position_callback,
            qos_profile)

        self.pose_pub = self.create_publisher(PoseStamped, '/drone_pose', 10)
        self.path_pub = self.create_publisher(Path, '/drone_path', 10)
        self.path_msg = Path()

    def position_callback(self, msg):
        self.get_logger().info(f&quot;Received: x={msg.x:.2f}, y={msg.y:.2f}&quot;)

        pose_msg = PoseStamped()
        pose_msg.header.stamp = self.get_clock().now().to_msg()
        pose_msg.header.frame_id = &quot;map&quot;
        
        pose_msg.pose.position.x = msg.y
        pose_msg.pose.position.y = msg.x
        pose_msg.pose.position.z = -msg.z
        pose_msg.pose.orientation.w = 1.0

        self.pose_pub.publish(pose_msg)
        self.path_msg.header = pose_msg.header
        self.path_msg.poses.append(pose_msg)
        self.path_pub.publish(self.path_msg)

def main(args=None):
    rclpy.init(args=args)
    node = DroneTrajectoryVisualizer()
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1777815763222&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#실행 권환 부여
chmod +x trajectory_node.py&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 setup.py를 수정합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1777815810368&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#~/ros_workspace/src/drone_viz_pkg/setup.py
entry_points={
        'console_scripts': [
            'trajectory_node = drone_viz_pkg.trajectory_node:main'
        ],
    },&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;워크스페이스로 이동해 빌드합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1777815923593&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd ~/ros_workspace
colcon build --packages-select drone_viz_pkg --symlink-install
source install/setup.bash&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정상적으로 빌드가 됐다면, &lt;br /&gt;실행해 봅시다.&lt;/p&gt;
&lt;pre id=&quot;code_1777816083899&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#터미널1
ros2 run drone_viz_pkg trajectory_node&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1777816160183&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#터미널2
MicroXRCEAgent udp4 -p 8888&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1777816181468&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#터미널3
cd ~/PX4-Autopilot
make px4_sitl gazebo-classic&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1777816196866&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#터미널4
rviz2&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 이쪽에 QGC를 띄워 조이스틱을 이용해 드론을 조작해 봤습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2560&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EITv2/dJMcadhAasI/dxmNDHKtkC1fIvLNSUJJNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EITv2/dJMcadhAasI/dxmNDHKtkC1fIvLNSUJJNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EITv2/dJMcadhAasI/dxmNDHKtkC1fIvLNSUJJNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEITv2%2FdJMcadhAasI%2FdxmNDHKtkC1fIvLNSUJJNK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2560&quot; height=&quot;1600&quot; data-origin-width=&quot;2560&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;position: absolute;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정상적으로 rviz에서 드론의 경로와 자세가 가시화되는 모습을 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>드론/PX4</category>
      <author>네 말이 옳다</author>
      <guid isPermaLink="true">https://he823.tistory.com/12</guid>
      <comments>https://he823.tistory.com/12#entry12comment</comments>
      <pubDate>Sun, 10 May 2026 09:00:19 +0900</pubDate>
    </item>
    <item>
      <title>#1 dq 변환</title>
      <link>https://he823.tistory.com/11</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;3상 모터는 시변계수가 포함되어 있어 모델링과 제어기 설계가 쉽지 않습니다.&lt;br /&gt;하지만, dq변환을 사용하면 전동기에 포함된 다양한 성분들의 시변계수를 제거할 수 있어 제어기 설계가 용이해집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 3상 모터 제어기 설계에 사용되는 dq변환에 대해서 알아보겠습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. 정지좌표계 변환&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dq변환의 가장 큰 목적은 &quot;교류의 파형을 직류처럼 해석&quot;하는 것입니다.&lt;br /&gt;그래서 abc 좌표계의 변수를 각속도 $\omega$로 회전하는 회전좌표계의 $d^\omega - q^\omega$ 변수로 변환해 주는 것이 목적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$\omega$의 속도로 회전하는 좌표계에 $\omega$의 속도로 움직이는 교류파형을 올려놓으면 직류처럼 보인다고 생각하시면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DQ변환은 기본적으로 2번에 걸쳐서 진행됩니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;정지좌표계 ($\alpha, \beta$) 변환&lt;/li&gt;
&lt;li&gt;회전좌표계 ($d, q$) 변환&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정지좌표계는 변환행렬 $T(\theta)$의 각도가 0인 상태를 의미합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$&lt;br /&gt;T(\theta) = \frac{2}{3}&lt;br /&gt;\begin{bmatrix}&lt;br /&gt;\cos\theta &amp;amp; \cos\left(\theta - \frac{2\pi}{3}\right) &amp;amp; \cos\left(\theta - \frac{4\pi}{3}\right)&lt;br /&gt;\\&lt;br /&gt;-\sin\theta &amp;amp; -\sin\left(\theta - \frac{2\pi}{3}\right) &amp;amp; -\sin\left(\theta - \frac{4\pi}{3}\right)&lt;br /&gt;\\&lt;br /&gt;\frac{1}{2} &amp;amp; \frac{1}{2} &amp;amp; \frac{1}{2}&lt;br /&gt;\end{bmatrix}&lt;br /&gt;$$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$\theta = 0$을 대입하면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$&lt;br /&gt;T(0) = \frac{2}{3}&lt;br /&gt;\begin{bmatrix}&lt;br /&gt;1 &amp;amp; -\frac{1}{2} &amp;amp; -\frac{1}{2} \\&lt;br /&gt;0 &amp;amp; \frac{\sqrt{3}}{2} &amp;amp; -\frac{\sqrt{3}}{2} \\&lt;br /&gt;\frac{1}{2} &amp;amp; \frac{1}{2} &amp;amp; \frac{1}{2}&lt;br /&gt;\end{bmatrix}&lt;br /&gt;$$&lt;br /&gt;이 되고, 여기에 abc상을 곱하여 정지좌표계 $\alpha, \beta$으로 변환할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$\alpha,\beta$ 로의 변환에서 2/3을 곱하는 이유는 변환 과정에서 abc상과의 크기를 동일하게 하기 위해서 사용됩니다.&lt;br /&gt;&lt;br /&gt;$$&lt;br /&gt;T(0) f_{abc} = f_{\alpha,\beta,o} &lt;br /&gt;$$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이를 시각화 한다면 다음과 같습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBldx2/dJMcaf7v0vB/5muwc7CpMhKQTIoSpUioc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBldx2/dJMcaf7v0vB/5muwc7CpMhKQTIoSpUioc0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBldx2/dJMcaf7v0vB/5muwc7CpMhKQTIoSpUioc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBldx2%2FdJMcaf7v0vB%2F5muwc7CpMhKQTIoSpUioc0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1200&quot; height=&quot;800&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;800&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 코드를 작성하고, 설계를 진행할 때는 A,B,C상 3개를 센싱하지 않습니다.&lt;br /&gt;상 3개는 평형이기 때문에 &lt;br /&gt;$&lt;br /&gt;V_a + V_b + V_c = 0&lt;br /&gt;$&lt;br /&gt;이므로&amp;nbsp;&lt;br /&gt;$V_c = -V_a - V_c$&amp;nbsp;&lt;br /&gt;로 표현할 수 있기 때문에 2개의 센서만 사용합니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. 회전좌표계 변환&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정지좌표계를 $\omega$의 속도로 회전시키면 회전좌표계로 변환이 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$&lt;br /&gt;\begin{bmatrix}&lt;br /&gt;V_d \\&lt;br /&gt;V_q \\&amp;nbsp;&lt;br /&gt;V_n&lt;br /&gt;\end{bmatrix}&lt;br /&gt;=&lt;br /&gt;\begin{bmatrix}&lt;br /&gt;\cos\theta &amp;amp; \sin\theta &amp;amp; 0 \\&lt;br /&gt;-\sin\theta &amp;amp; \cos\theta &amp;amp; 0 \\&lt;br /&gt;0 &amp;amp;0 &amp;amp; 1&lt;br /&gt;\end{bmatrix}&lt;br /&gt;\begin{bmatrix}&lt;br /&gt;V_\alpha \\&lt;br /&gt;V_\beta \\&lt;br /&gt;V_n&lt;br /&gt;\end{bmatrix}&lt;br /&gt;$$&lt;br /&gt;이를 시각화하면,&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbvvlE/dJMcag6rP0c/Hg3omHFVA2YT7Pjn4M4BC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbvvlE/dJMcag6rP0c/Hg3omHFVA2YT7Pjn4M4BC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbvvlE/dJMcag6rP0c/Hg3omHFVA2YT7Pjn4M4BC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcbvvlE%2FdJMcag6rP0c%2FHg3omHFVA2YT7Pjn4M4BC0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1200&quot; height=&quot;800&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;800&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dq 좌표계에서 관측하면 $\alpha-\beta$ 평면에서 회전하던 벡터가 정지하게 되어, $V_d$는 일정한 값(DC)으로 나타나고 $V_q$는 0에 가까운 값이 됩니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>전력전자/모터</category>
      <author>네 말이 옳다</author>
      <guid isPermaLink="true">https://he823.tistory.com/11</guid>
      <comments>https://he823.tistory.com/11#entry11comment</comments>
      <pubDate>Sat, 9 May 2026 19:01:15 +0900</pubDate>
    </item>
    <item>
      <title>#1 ROS Sensor Topic</title>
      <link>https://he823.tistory.com/9</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Ros는 기능을 Node로 나누고,&lt;br /&gt;Node끼리는 Topic을 통해 데이터를 주고 받을 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;배터리 노드 : 배터리의 전압, 전류, 용량등&lt;/li&gt;
&lt;li&gt;모터 제어 노드 : 속도 및 위치등을 제어&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가 있고, &lt;u&gt;배터리 전압&lt;/u&gt;에 따른 &lt;u&gt;비상정지 기능&lt;/u&gt;을 구현한다면&lt;br /&gt;&lt;br /&gt;배터리 노드는 지속적으로 자신의 전압과 전류 데이터&lt;b&gt;Topic&lt;/b&gt;을 &lt;b&gt;Publish&lt;/b&gt;합니다.&lt;br /&gt;모터 제어 노드는 전압과 전류 데이터&lt;b&gt;Topic&lt;/b&gt;을&amp;nbsp;&lt;b&gt;Subscribe&lt;/b&gt;해서 모터를 제어하는 방식이죠.&lt;br /&gt;&lt;br /&gt;이번에는 ROS1에서 &lt;u&gt;&lt;b&gt;카메라 Sensor 데이터를 발행&lt;/b&gt;&lt;/u&gt;해보고 &lt;u&gt;&lt;b&gt;Rviz를 통해 가시화&lt;/b&gt;&lt;/u&gt; 된 데이터를 확인해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;환경&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;Jetson Orin Ubuntu 20.04&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;ROS1 noetic&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. 카메라 테스트&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카메라는 다른 컴퓨터(192.168.0.21)에 장착되어 있습니다.&lt;br /&gt;카메라(CSI MIPI)가 정상적으로 인식된 상태인지 확인합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1776605894521&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ls /dev/video*&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SSH로 원격으로 접속한 상태이기 때문에 GUI를 활용해 Video가 정상 작동되는지 확인할 수 없습니다.&lt;br /&gt;Gstreamer를 이용해 5600번 Port로 영상을 송출하여 정상 작동하는지 확인하겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1776607235210&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;gst-launch-1.0 -v \
nvarguscamerasrc ! \
'video/x-raw(memory:NVMM),width=1280,height=720,framerate=30/1' ! \
nvvidconv ! \
nvv4l2h264enc bitrate=2000000 insert-sps-pps=true ! \
h264parse ! \
mpegtsmux ! \
udpsink host=192.168.0.3 port=5600 #192.168.0.3은 HOST PC&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 VLC에서&lt;/p&gt;
&lt;pre id=&quot;code_1776612413528&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;udp://@:5600&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2558&quot; data-origin-height=&quot;1342&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vDg6x/dJMb99TB6AJ/2JGrrpRyQo5Bw2bKfplTt1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vDg6x/dJMb99TB6AJ/2JGrrpRyQo5Bw2bKfplTt1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vDg6x/dJMb99TB6AJ/2JGrrpRyQo5Bw2bKfplTt1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvDg6x%2FdJMb99TB6AJ%2F2JGrrpRyQo5Bw2bKfplTt1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2558&quot; height=&quot;1342&quot; data-origin-width=&quot;2558&quot; data-origin-height=&quot;1342&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. Sensor Topic Publish&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카메라 센서는 192.168.0.21에 부착되어 있다고 하였습니다.&lt;br /&gt;192.168.0.21에서 Topic을 Publish 하도록 하겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1776613026071&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#192.168.0.21에서 수행
#터미널 1
source /opt/ros/noetic/setup.bash
roscore&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 파일을 작성하고 실행합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1776612515057&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#!/usr/bin/env python3
import os
os.environ[&quot;ROS_MASTER_URI&quot;] = &quot;http://192.168.0.21:11311&quot;
os.environ[&quot;ROS_IP&quot;] = &quot;192.168.0.21&quot;

import cv2
import rospy
from sensor_msgs.msg import Image
from cv_bridge import CvBridge

pipeline = (
    &quot;nvarguscamerasrc ! &quot;
    &quot;video/x-raw(memory:NVMM),width=1280,height=720,framerate=30/1 ! &quot;
    &quot;nvvidconv ! &quot;
    &quot;video/x-raw,format=BGRx ! &quot;
    &quot;videoconvert ! &quot;
    &quot;video/x-raw,format=BGR ! &quot;
    &quot;appsink drop=true max-buffers=1 sync=false&quot;
)

def main():
    rospy.init_node(&quot;camera_pub&quot;)
    pub = rospy.Publisher(&quot;/camera/image_raw&quot;, Image, queue_size=1)
    bridge = CvBridge()

    cap = cv2.VideoCapture(pipeline, cv2.CAP_GSTREAMER)

    if not cap.isOpened():
        rospy.logerr(&quot;Failed to open camera with GStreamer pipeline&quot;)
        return

    rate = rospy.Rate(30)

    while not rospy.is_shutdown():
        ret, frame = cap.read()
        if not ret:
            rospy.logwarn(&quot;Failed to read frame from camera&quot;)
            rate.sleep()
            continue

        msg = bridge.cv2_to_imgmsg(frame, encoding=&quot;bgr8&quot;)
        msg.header.stamp = rospy.Time.now()
        msg.header.frame_id = &quot;camera&quot;
        pub.publish(msg)

        rate.sleep()

    cap.release()

if __name__ == &quot;__main__&quot;:
    main()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. Sensor Topic Subscribe&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;192.168.0.21에서 Publish한 Topic을 Subscribe하고 이를 Rviz로 가시화해보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1776613368769&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#192.168.0.3에서 수행
nano ~/.bashrc&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 하단에&lt;/p&gt;
&lt;pre id=&quot;code_1776613526595&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export ROS_MASTER_URI=http://192.168.0.21:11311
export ROS_IP=192.168.0.3&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;을 추가하고 저장합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1776613640652&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;source ~/.bashrc
source /opt/ros/noetic/setup.bash
rviz&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷, 2026-04-20 00-48-04.png&quot; data-origin-width=&quot;2484&quot; data-origin-height=&quot;1496&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lqJkp/dJMcahxmWAU/fDKtHyi8Qf3bFo2Kdkc3y1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lqJkp/dJMcahxmWAU/fDKtHyi8Qf3bFo2Kdkc3y1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lqJkp/dJMcahxmWAU/fDKtHyi8Qf3bFo2Kdkc3y1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlqJkp%2FdJMcahxmWAU%2FfDKtHyi8Qf3bFo2Kdkc3y1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2484&quot; height=&quot;1496&quot; data-filename=&quot;스크린샷, 2026-04-20 00-48-04.png&quot; data-origin-width=&quot;2484&quot; data-origin-height=&quot;1496&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정상적으로 영상이 출력되는 모습을 확인할 수 있습니다.&lt;/p&gt;</description>
      <category>드론/ROS</category>
      <author>네 말이 옳다</author>
      <guid isPermaLink="true">https://he823.tistory.com/9</guid>
      <comments>https://he823.tistory.com/9#entry9comment</comments>
      <pubDate>Sat, 2 May 2026 01:49:07 +0900</pubDate>
    </item>
    <item>
      <title>#2 MAVlink Router</title>
      <link>https://he823.tistory.com/10</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이전 게시글에서는 MAVSDK를 사용하는 방법에 대해서 설명하였습니다.&lt;br /&gt;이번에는, MAVlink Router를 이용해서 Endpoint에서 MAVlink 데이터를 수신하는 방법에 대해서 설명하겠습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. 왜 MAVlink Router를 사용하는가?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FC를 Offboard 모드로 사용하기 위해선 Jetson, Raspberry pi등의 Companion Computer가 필요합니다.&lt;br /&gt;그러면, &quot;PC에서 드론의 상태를 어떻게 볼 것이고, Companion Computer를 어떻게 접속할까?&quot; 에 대해 생각해 볼 필요가 있습니다.&lt;br /&gt;&lt;br /&gt;PC(QGC)에서 드론(PX4)으로 접속하기 위해선 드론이 현재 상태(Mavlink Data)를 PC의 특정 포트로 보내주어야 합니다.&lt;br /&gt;PC에서 Companion Computer에 접속하여 Offboard 명령을 주기 위해서는 SSH등으로 Companion Computer에 접속하여야 합니다.&lt;br /&gt;&lt;br /&gt;그러면, PC &amp;lt;-&amp;gt; 드론&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; PC &amp;lt;-&amp;gt; Companion Computer&lt;br /&gt;2개의 통신 링크가 필요합니다.&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;br /&gt;하지만&lt;br /&gt;Drone &amp;lt;-&amp;gt; Companion Computer &amp;lt;-&amp;gt; PC&amp;nbsp;&lt;br /&gt;와 같이 구성하고 Companion Computer가 PC와 드론의 중간다리 역할을 해준다면 시스템이 매우 간단해집니다.&lt;br /&gt;&lt;br /&gt;그 중간다리 역할을 해주는 것이 MAVlink Router입니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. 드론의 통신 시스템&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MAVlink Router를 사용한 드론의 통신 시스템을 그림으로 간단히 설명해보자면 다음과 같이 표현될 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;그림1.png&quot; data-origin-width=&quot;3030&quot; data-origin-height=&quot;610&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ECwle/dJMcajaUnCC/ZWBUOHxTKMiF1qGNg5ECU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ECwle/dJMcajaUnCC/ZWBUOHxTKMiF1qGNg5ECU1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ECwle/dJMcajaUnCC/ZWBUOHxTKMiF1qGNg5ECU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FECwle%2FdJMcajaUnCC%2FZWBUOHxTKMiF1qGNg5ECU1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3030&quot; height=&quot;610&quot; data-filename=&quot;그림1.png&quot; data-origin-width=&quot;3030&quot; data-origin-height=&quot;610&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면, PC에서 Drone의 MAVlink Data를 받아오기 위해서 Companion Computer가 Bridge역할을 해줘야 합니다.&lt;br /&gt;UART로 입 출력 되는 MAVlink 데이터를 PC로 전달해주어야 정상적으로 PC에서 드론의 상태를 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MAVlink Router를 이용하면 각 Endpoint간에 통신 프로토콜을 선택해 MAVlink 데이터를 주고 받게 할 수 있습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. MAVlink Router SETUP&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치는 Companion Computer에서 진행합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1777125031904&quot; class=&quot;jboss-cli&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;git clone https://github.com/mavlink-router/mavlink-router.git
cd mavlink-router
git submodule update --init --recursive&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제가 사용하는 Companion Computer는 apt 로 meson을 설치하면 0.53으로 설치되어 그 이상의 버전을 다운받기 위해서는 직접 바이너리를 다운 받고 적용해주어야 했습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1777125171389&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mkdir meson
cd meson
wget https://github.com/mesonbuild/meson/releases/download/0.64.1/meson-0.64.1.tar.gz
tar -xzf meson-0.64.1.tar.gz

export MESON_PATH=~/meson
cp meson.py meson
chmod +x meson
sudo ln -s $MESON_PATH/meson /usr/bin/meson
echo 'export PATH=$PATH:$MESON_PATH' &amp;gt;&amp;gt; ~/.bashrc
source ~/.bashrc&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 meson과 ninja를 이용해 Build후 install합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1777125365097&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;meson setup build .
ninja -C build
sudo ninja -C build install&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;conf파일을 생성합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1777125431690&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;nano test.conf

[UartEndpoint Telemetry_Drone1]
Device = /dev/ttyTHS0
Baud = 921600

[UdpEndpoint qgc_pc]
Mode = Normal
Address = 192.168.0.1
Port = 14540&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 Device는 Companion에 연결된 UART port를 선택하면 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1777125701661&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mavlink-routerd -c test.conf&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 커맨드를 이용해 mavlink router를 작동시킵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 같은 과정으로 PC와 Drone을 연결할 수 있습니다.&lt;/p&gt;</description>
      <category>드론/PX4</category>
      <author>네 말이 옳다</author>
      <guid isPermaLink="true">https://he823.tistory.com/10</guid>
      <comments>https://he823.tistory.com/10#entry10comment</comments>
      <pubDate>Fri, 1 May 2026 09:17:57 +0900</pubDate>
    </item>
    <item>
      <title># 0 Docker를 활용한 ROS1 개발환경 구축</title>
      <link>https://he823.tistory.com/8</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Docker를 이용해 PC의 구성 환경을 분리할 수 있습니다.&lt;br /&gt;&lt;br /&gt;Ubuntu 20.04에서 가상환경을 이용해 ROS1 개발환경을 구축하고 ROS2와 동시에 설치될 수 있도록 하겠습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. Docker설치&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PC에서 ROS1과 2를 구동하기 위해서는 Docker를 사용해 환경을 분리해야 합니다.&lt;br /&gt;두개를 동시에 설치하면 의존성 문제로 충돌할 가능성이 있기 때문이죠.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 Docker를 설치하겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1776514324772&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo apt-get update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

echo \
  &quot;deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release &amp;amp;&amp;amp; echo &quot;$VERSION_CODENAME&quot;) stable&quot; | \
  sudo tee /etc/apt/sources.list.d/docker.list &amp;gt; /dev/null
  
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginsudo apt install -y docker-ce dsudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginocker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. ROS1 설치&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Rviz 및 GUI가 포함된 ROS1을 설치해야하기 때문에 desktop/full 을 설치하겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1776514530377&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker pull osrf/ros:noetic-desktop-full&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. Docker 실행&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;호스트의 X서버가 컨테이너와 통신할 수 있도록 허용하기 위해 X11 forwarding을 활성화 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1776516708300&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;xhost +local:docker&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;docker를 실행합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1776515441215&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo docker run -dit \
  --name ros1 \
  --network host \
  --privileged \
  -v=/dev:/dev \
  --device /dev/dri \
  -e DISPLAY=$DISPLAY \
  -e LIBGL_ALWAYS_SOFTWARE=1 \
  -v /tmp/.X11-unix:/tmp/.X11-unix:rw \
  -v ~/catkin_ws:/root/catkin_ws \
  osrf/ros:noetic-desktop-full \
  bash&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명령어를 하나하나 살펴본다면&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;-dit : 백그라운드 실행으로 Container에서 터미널 명령을 사용할 수 있게 하는 옵션&lt;/li&gt;
&lt;li&gt;&lt;span&gt;--name&lt;/span&gt;&lt;span&gt; ros1&lt;/span&gt; : Container의 이름을 ros1으로 설정&lt;/li&gt;
&lt;li&gt;&lt;span&gt;--network&lt;/span&gt;&lt;span&gt; host&lt;/span&gt; : Host의 네트워크를 그대로 사용&lt;/li&gt;
&lt;li&gt;--privileged: Container에서 시스템의 주요 자원에 접근&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&amp;nbsp;-v= /dev:/dev : /dev 폴더가 Host의 /dev 폴더에 연결&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;--device&lt;/span&gt;&lt;span&gt; /dev/dri&lt;/span&gt; : 그래픽 관련 장치 사용&lt;/li&gt;
&lt;li&gt;-e DISPLAY=$DISPLAY \ : Host에 GUI를 출력하도록 함&lt;/li&gt;
&lt;li&gt;-v /tmp/.X11-unix:/tmp/.X11-unix:rw : Host에 GUI를 출력하도록 함&lt;/li&gt;
&lt;li&gt;-v ~/catkin_ws:/root/catkin_ws : Host의 ~/catkin_ws 폴더를 컨테이너 /root/catkin_ws 와 연결&lt;/li&gt;
&lt;li&gt;&lt;span&gt;osrf/ros:noetic-desktop-full&lt;/span&gt; : 사용할 이미지 이름&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후에 어떻게 사용할지에 따라서 유연하게 변경하도록 하겠습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. Rviz로 가시화&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Rviz에서 정상적으로 토픽이 발행되는지 확인합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1776515750032&quot; class=&quot;armasm&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;#터미널 1번
sudo docker exec -it ros1 bash
source /opt/ros/noetic/setup.bash
roscore

#터미널 2번
sudo docker exec -it ros1 bash
source /opt/ros/noetic/setup.bash
rviz&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1776515654977&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#터미널 3번
sudo docker exec -it ros1 bash
source /opt/ros/noetic/setup.bash

rostopic pub /visualization_marker visualization_msgs/Marker &quot;header:
  frame_id: 'map'
ns: 'test'
id: 0
type: 2
action: 0
pose:
  position: {x: 1.0, y: 0.0, z: 0.0}
  orientation: {x: 0.0, y: 0.0, z: 0.0, w: 1.0}
scale: {x: 0.2, y: 0.2, z: 0.2}
color: {a: 1.0, r: 0.0, g: 1.0, b: 0.0}&quot; -r 10&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷, 2026-04-18 21-33-14.png&quot; data-origin-width=&quot;5124&quot; data-origin-height=&quot;2884&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xz7mp/dJMcaiC0o97/MFZtXedc4rxxQrQKjQuIsK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xz7mp/dJMcaiC0o97/MFZtXedc4rxxQrQKjQuIsK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xz7mp/dJMcaiC0o97/MFZtXedc4rxxQrQKjQuIsK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fxz7mp%2FdJMcaiC0o97%2FMFZtXedc4rxxQrQKjQuIsK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;5124&quot; height=&quot;2884&quot; data-filename=&quot;스크린샷, 2026-04-18 21-33-14.png&quot; data-origin-width=&quot;5124&quot; data-origin-height=&quot;2884&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정상적으로 토픽이 가시화 되는 것을 확인 할 수 있습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5. Serial 통신 확인&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Serial 통신이 재대로 되는지도 확인해보겠습니다.&lt;br /&gt;테스트용으로 사용하고 있는 Cube orange+를 usb로 연결하겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1776518188390&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ls /dev/tty*&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷, 2026-04-18 22-15-44.png&quot; data-origin-width=&quot;1410&quot; data-origin-height=&quot;648&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c8cPmt/dJMcajojKEz/s2hV8qkiLz7r45UWK8eadk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c8cPmt/dJMcajojKEz/s2hV8qkiLz7r45UWK8eadk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c8cPmt/dJMcajojKEz/s2hV8qkiLz7r45UWK8eadk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc8cPmt%2FdJMcajojKEz%2Fs2hV8qkiLz7r45UWK8eadk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1410&quot; height=&quot;648&quot; data-filename=&quot;스크린샷, 2026-04-18 22-15-44.png&quot; data-origin-width=&quot;1410&quot; data-origin-height=&quot;648&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가상환경 내에서 /dev/ttyACM0가 정상적으로 인식되는 것을 확인 할 수 있습니다&lt;/p&gt;</description>
      <category>드론/ROS</category>
      <author>네 말이 옳다</author>
      <guid isPermaLink="true">https://he823.tistory.com/8</guid>
      <comments>https://he823.tistory.com/8#entry8comment</comments>
      <pubDate>Sun, 26 Apr 2026 23:17:39 +0900</pubDate>
    </item>
    <item>
      <title>#4 인버터 구동 - 인버터 제작의 실질적 애로사항</title>
      <link>https://he823.tistory.com/5</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이전 게시글에서 Ti의 MCU를 이용해 SPWM을 발생하기 까지의 과정에 대해서 설명했습니다.&lt;br /&gt;이번에는 인버터를 제작할 때 이론과 실제적용의 차이점에 대해서 설명하도록 하겠습니다.&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. How To Control Gate-Source Surge Voltage&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 신경썻던 부분은 MOSFET의&amp;nbsp;&lt;b&gt;게이트-소스 양단의 서지전압을 어떻게 컨트롤 할 것인가&lt;/b&gt;에 대해서입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1645&quot; data-origin-height=&quot;772&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bq4Oyk/dJMcagLUKj9/ksKU5sGXcOWeysRKXPMCRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bq4Oyk/dJMcagLUKj9/ksKU5sGXcOWeysRKXPMCRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bq4Oyk/dJMcagLUKj9/ksKU5sGXcOWeysRKXPMCRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbq4Oyk%2FdJMcagLUKj9%2FksKU5sGXcOWeysRKXPMCRk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1645&quot; height=&quot;772&quot; data-origin-width=&quot;1645&quot; data-origin-height=&quot;772&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Gate - Source surge voltage를 +26V에서 -4V 사이에서 제어하라고 추천하고 있습니다. &lt;br /&gt;만약 이를 초과하는 전압을 인가했을 시에는 FET가 소손될수 있습니다. &lt;br /&gt;그 외에도 나중에 설명하겠지만, Gate-Source Surge Voltage는 인버터 손실의 원인이 되므로 제거하는 것이 바람직합니다&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게이트 소스 서지전압은 대부분 인덕턴스에 의해 발생합니다.&lt;br /&gt;$V= L\frac{di}{dt}$이므로 전류의 변화에 따라서 전압이 발생하고 이는 서지 전압으로 이어집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;그러면 서지 전압을 줄이기 위해서는 &lt;b&gt;2개의 변수를 제어&lt;/b&gt;하면 됩니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;전류의 변화량&lt;/li&gt;
&lt;li&gt;인덕턴스&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전류의 변화량은 컨트롤 하기 힘듭니다. &lt;br /&gt;부하가 늘어나면 전류의 변화량도 커지고, 스위칭 속도가 빠르면 빠를 수록 전류의 변화량은 증가합니다.&lt;br /&gt;그러므로 서지 전압을 최소화하기 위해서는 회로 내의 인덕턴스를 낮추어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인덕턴스는 다음 조건에서 상승합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;전선이 길어질 수록&lt;/li&gt;
&lt;li&gt;전선이 얇을 수록&lt;/li&gt;
&lt;li&gt;회로 내의 루프가 클 수록&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1,2번의 이유로 PCB를 제작할 때 최대한 짧은 전선의 배치가 필요합니다.&lt;br /&gt;최대한 전선을 짧게 배치하고 정격에 맞는 배선굵기를 선택하는 것이 좋습니다.&lt;br /&gt;3번의 이유로 인버터의 소자는 THM 타입이 아닌 SMD타입의 사용이 필수적입니다. 또한 같은 이유로 완성품은 브레드보드 또는 만능기판에 납땜으로 마무리 하는 것이 아닌, PCB를 제작해서 회로를 구성하는 것이 바람직합니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2-1. Surge Voltage Control - PCB, 만능기판의 차이점&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cyzZeO/dJMcadau9Rs/7NQJcCba0PLpREUkjliRik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cyzZeO/dJMcadau9Rs/7NQJcCba0PLpREUkjliRik/img.png&quot; data-origin-width=&quot;519&quot; data-origin-height=&quot;533&quot; data-is-animation=&quot;false&quot; style=&quot;width: 35.1472%; margin-right: 10px;&quot; data-widthpercent=&quot;35.56&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cyzZeO/dJMcadau9Rs/7NQJcCba0PLpREUkjliRik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcyzZeO%2FdJMcadau9Rs%2F7NQJcCba0PLpREUkjliRik%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;519&quot; height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9G5LW/dJMcajaJ41f/q2zKjKcEUVxQMnT300Remk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9G5LW/dJMcajaJ41f/q2zKjKcEUVxQMnT300Remk/img.png&quot; data-origin-width=&quot;1004&quot; data-origin-height=&quot;569&quot; data-is-animation=&quot;false&quot; style=&quot;width: 63.69%;&quot; data-widthpercent=&quot;64.44&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9G5LW/dJMcajaJ41f/q2zKjKcEUVxQMnT300Remk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9G5LW%2FdJMcajaJ41f%2Fq2zKjKcEUVxQMnT300Remk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1004&quot; height=&quot;569&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;만능기판에 회로를 구성하고 동작한 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dvll9n/dJMcahD0Jrn/RUP1ZTVK3dkUtHnAklXUv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dvll9n/dJMcahD0Jrn/RUP1ZTVK3dkUtHnAklXUv1/img.png&quot; data-origin-width=&quot;518&quot; data-origin-height=&quot;533&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;36.78&quot; style=&quot;width: 36.3491%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dvll9n/dJMcahD0Jrn/RUP1ZTVK3dkUtHnAklXUv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdvll9n%2FdJMcahD0Jrn%2FRUP1ZTVK3dkUtHnAklXUv1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;518&quot; height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buQxAb/dJMcacW0Qml/cvV23xrMJ3A0ojUx31f551/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buQxAb/dJMcacW0Qml/cvV23xrMJ3A0ojUx31f551/img.png&quot; data-origin-width=&quot;959&quot; data-origin-height=&quot;574&quot; data-is-animation=&quot;false&quot; style=&quot;width: 62.4881%;&quot; data-widthpercent=&quot;63.22&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buQxAb/dJMcacW0Qml/cvV23xrMJ3A0ojUx31f551/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuQxAb%2FdJMcacW0Qml%2FcvV23xrMJ3A0ojUx31f551%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;959&quot; height=&quot;574&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;PCB(THM)에 회로를 구성하고 동작한 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 사진은 만능기판을 사용한 스위칭 회로와 PCB를 사용한 스위칭 회로의 서지전압 파형 비교 사진입니다.&lt;br /&gt;확실히 PCB를 사용했을 때 &lt;b&gt;낮은 인덕턴스&lt;/b&gt;로 인해 &lt;b&gt;서지 전압이 줄어든 것&lt;/b&gt;을 확인 할 수 있습니다.&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2-2. Surge Voltage Control - THM, SMD 소자 사용의 차이점&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3CAKo/dJMcagZprmW/EHk8waOGAoCfVEOI91YWsk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3CAKo/dJMcagZprmW/EHk8waOGAoCfVEOI91YWsk/img.png&quot; data-origin-width=&quot;321&quot; data-origin-height=&quot;329&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;37.57&quot; style=&quot;width: 37.1351%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3CAKo/dJMcagZprmW/EHk8waOGAoCfVEOI91YWsk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3CAKo%2FdJMcagZprmW%2FEHk8waOGAoCfVEOI91YWsk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;321&quot; height=&quot;329&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/drDyvv/dJMcad2EoPM/MkkOQeLiDrCL1LQZm79Vmk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/drDyvv/dJMcad2EoPM/MkkOQeLiDrCL1LQZm79Vmk/img.png&quot; data-origin-width=&quot;843&quot; data-origin-height=&quot;520&quot; data-is-animation=&quot;false&quot; style=&quot;width: 61.7021%;&quot; data-widthpercent=&quot;62.43&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/drDyvv/dJMcad2EoPM/MkkOQeLiDrCL1LQZm79Vmk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdrDyvv%2FdJMcad2EoPM%2FMkkOQeLiDrCL1LQZm79Vmk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;843&quot; height=&quot;520&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;THM 사용 회로&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LB2Jp/dJMcaa5Zscl/DyfNwYCRUQZPt5KCdGg9Ok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LB2Jp/dJMcaa5Zscl/DyfNwYCRUQZPt5KCdGg9Ok/img.png&quot; data-origin-width=&quot;322&quot; data-origin-height=&quot;331&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;37.31&quot; style=&quot;width: 36.8807%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LB2Jp/dJMcaa5Zscl/DyfNwYCRUQZPt5KCdGg9Ok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLB2Jp%2FdJMcaa5Zscl%2FDyfNwYCRUQZPt5KCdGg9Ok%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;322&quot; height=&quot;331&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bf75SF/dJMcagLUKnm/BKGkE6ZbVw5wbMWIhnbxL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bf75SF/dJMcagLUKnm/BKGkE6ZbVw5wbMWIhnbxL1/img.png&quot; data-origin-width=&quot;840&quot; data-origin-height=&quot;514&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;62.69&quot; style=&quot;width: 61.9565%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bf75SF/dJMcagLUKnm/BKGkE6ZbVw5wbMWIhnbxL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbf75SF%2FdJMcagLUKnm%2FBKGkE6ZbVw5wbMWIhnbxL1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;840&quot; height=&quot;514&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;SMD 사용 회로&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 사진은 THM타입과 SMD타입으로 회로를 구성한 사진입니다. &lt;br /&gt;그림 의 사진이 훨신 루프와 배선 길이가 짧아져 인덕턴스가 감소해 서지전압이 감소한것을 볼 수 있습니다.&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2-3. Surge Voltage Control - Kelvin Source MOSFET 사용의 이점&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회로 내의 인덕턴스를 감소하는 방법은 이뿐만이 아닙니다. FET내부의 Source단에 존재하는 인덕턴스를 제거하는 방법이 존재합니다. Kelvin Source MOSFET은 파워 Source를 분리시켜 서지 발생 원인인 인덕턴스를 회로에서 제거한 FET모델입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;975&quot; data-origin-height=&quot;444&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QcD3X/dJMcadBym2B/kDHBtoAgXYT1e2fCgKPPSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QcD3X/dJMcadBym2B/kDHBtoAgXYT1e2fCgKPPSK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QcD3X/dJMcadBym2B/kDHBtoAgXYT1e2fCgKPPSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQcD3X%2FdJMcadBym2B%2FkDHBtoAgXYT1e2fCgKPPSK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;720&quot; height=&quot;328&quot; data-origin-width=&quot;975&quot; data-origin-height=&quot;444&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 사진은 Kelvin Source MOSFET입니다. 파워소스와 드라이버소스를 분리시켜 인덕턴스에 의한 서지 전압을 최소화 할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;475&quot; data-origin-height=&quot;332&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7HqXZ/dJMcaibTBXj/7AmMZgx51UBY2MjxFBCFL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7HqXZ/dJMcaibTBXj/7AmMZgx51UBY2MjxFBCFL0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7HqXZ/dJMcaibTBXj/7AmMZgx51UBY2MjxFBCFL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7HqXZ%2FdJMcaibTBXj%2F7AmMZgx51UBY2MjxFBCFL0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;475&quot; height=&quot;332&quot; data-origin-width=&quot;475&quot; data-origin-height=&quot;332&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 위의 사진에서 $&lt;span&gt;L_{source}$ &lt;/span&gt;를 제거한 모델이라 생각하면 됩니다. 이를 수식으로 표현하면 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$V_{GS} = V_G - I_G\times R_{G_{EXT}} - L_{source} \times \frac{dI_D}{dt}$$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 $&lt;span&gt;L_{TRACE}$&lt;/span&gt;에 대한 인덕턴스만 남게되고, 인덕턴스를 최소화 할 수 있게 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cXGBc2/dJMcaf0uHdW/2vmS8LmdniqvIW5nyT25lK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cXGBc2/dJMcaf0uHdW/2vmS8LmdniqvIW5nyT25lK/img.png&quot; data-origin-width=&quot;767&quot; data-origin-height=&quot;444&quot; data-is-animation=&quot;false&quot; style=&quot;width: 51.0783%; margin-right: 10px;&quot; data-widthpercent=&quot;51.68&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cXGBc2/dJMcaf0uHdW/2vmS8LmdniqvIW5nyT25lK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcXGBc2%2FdJMcaf0uHdW%2F2vmS8LmdniqvIW5nyT25lK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;767&quot; height=&quot;444&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/djrzsT/dJMcaf0uHdZ/sa90sljJUvTN2tyqZnHFxK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/djrzsT/dJMcaf0uHdZ/sa90sljJUvTN2tyqZnHFxK/img.png&quot; data-origin-width=&quot;722&quot; data-origin-height=&quot;447&quot; data-is-animation=&quot;false&quot; style=&quot;width: 47.7589%;&quot; data-widthpercent=&quot;48.32&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/djrzsT/dJMcaf0uHdZ/sa90sljJUvTN2tyqZnHFxK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdjrzsT%2FdJMcaf0uHdZ%2Fsa90sljJUvTN2tyqZnHFxK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;722&quot; height=&quot;447&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 사진은 3pin과 4pin MOSFET의 비교 사진입니다. -2V의 서지 전압이 개선된 것을 볼 수 있습니다.&lt;br /&gt;결론적으로, 위의 실험들로 다음과 같은 결론을 얻었습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;브레드보드 또는 만능기판에서 결선은 배선 인덕턴스의 상승을 초래한다.&lt;/li&gt;
&lt;li&gt;회로 내 전선의 길이는 최대한 짧고 적절한 굵기로 구성한다.&lt;/li&gt;
&lt;li&gt;회로 내의 루프는 최소화한다.&lt;/li&gt;
&lt;li&gt;THM타입보단, SMD타입을 사용한다.&lt;/li&gt;
&lt;li&gt;3pin FET보단, Kelvin Source FET를 사용한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. How To Control Drain-Source Surge Voltage&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;빠른 스위칭으로 인해 Gate에만 서지 전압이 인가되는 것은 아닙니다.&lt;br /&gt;Drain에도 서지 전압이 발생합니다. 이 또한 인덕턴스에 의한 발생이 주된 원인입니다.&lt;br /&gt;이를 감소하기 위해서는 당연히 짧은 전선 배치가 필요합니다. 하지만 짧은 전선 배치만으로는 높은 전류에 의한 서지 전압을 막을 수 없습니다.&lt;br /&gt;제가 제어했던 유도전동기는 3kW급으로 정격 전류가 12A정도입니다. 기동할 때 발생하는 전류는 그보다 더 클 수 있습니다. 그러므로 전류에 의한 서지 전압의 영향은 매우 큽니다.&lt;br /&gt;&lt;br /&gt;Drain-Source의 서지전압을 감소하기 위해서는 스너버커페시터가 필요합니다.&lt;br /&gt;스너버커패시터는 하이사이드 드레인과 로우사이드 소스에 삽입되며 스위칭 소자와 매우 가까이 배치되어야 합니다.&lt;br /&gt;커패시터는 고주파 특성이 좋은 필름 커패시터를 사용합니다. 서지 전압은 대부분 고주파로 구성되어 있기 때문에 DC link 평활용으로 사용하는 알루미늄 커패시터는 효과가 미미합니다.&lt;br /&gt;일반적으로 동일 용량 및 정격전압에서 필름 커패시터는 알루미늄 커패시터보다 비싸기 때문에 평활용으로 높은 용량의 알루미늄 커패시터를 배치하고, 높은 정격전압에 낮은 용량의 필름커패시터를 선택합니다.&lt;br /&gt;또한 낮은 ESR, ESL의 소자를 선택하는 것이 중요합니다. 커패시터에서 에너지가 흡수되기 때문에 인덕턴스와 저항이 클 수록 흡수율이 낮아집니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wJuRe/dJMcab4SE5s/hYpl0jRkttC86dSM1OhpT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wJuRe/dJMcab4SE5s/hYpl0jRkttC86dSM1OhpT1/img.png&quot; style=&quot;width: 50.1095851380733%;&quot; data-widthpercent=&quot;50.7&quot; data-is-animation=&quot;false&quot; data-origin-height=&quot;650&quot; data-origin-width=&quot;1058&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wJuRe/dJMcab4SE5s/hYpl0jRkttC86dSM1OhpT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwJuRe%2FdJMcab4SE5s%2FhYpl0jRkttC86dSM1OhpT1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1058&quot; height=&quot;650&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uwv5v/dJMcafTLm79/uXYiP7p44ykKe2b8FpoyB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uwv5v/dJMcafTLm79/uXYiP7p44ykKe2b8FpoyB0/img.png&quot; style=&quot;width: 48.727624164252276%;&quot; data-widthpercent=&quot;49.3&quot; data-is-animation=&quot;false&quot; data-origin-height=&quot;628&quot; data-origin-width=&quot;994&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uwv5v/dJMcafTLm79/uXYiP7p44ykKe2b8FpoyB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fuwv5v%2FdJMcafTLm79%2FuXYiP7p44ykKe2b8FpoyB0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;994&quot; height=&quot;628&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;위의 사진은 스너버 커패시터가 없는 Drain-Source 전압 파형과 배치한 Drain-Source전압입니다.&lt;br /&gt;스너버 커패시터가 있는 우측의 파형에서 안정적으로 스위칭 하는 모습을 볼 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/G5VxB/dJMcaiCVmCD/tJxgAGgOGUkKk4ANf0VzQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/G5VxB/dJMcaiCVmCD/tJxgAGgOGUkKk4ANf0VzQk/img.png&quot; style=&quot;width: 50.36016805192598%;&quot; data-widthpercent=&quot;50.95&quot; data-is-animation=&quot;false&quot; data-origin-height=&quot;648&quot; data-origin-width=&quot;1140&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/G5VxB/dJMcaiCVmCD/tJxgAGgOGUkKk4ANf0VzQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FG5VxB%2FdJMcaiCVmCD%2FtJxgAGgOGUkKk4ANf0VzQk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1140&quot; height=&quot;648&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TDMOo/dJMcaiCVmCC/NGdad1FN0ejEY8biRlFBOK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TDMOo/dJMcaiCVmCC/NGdad1FN0ejEY8biRlFBOK/img.png&quot; style=&quot;width: 48.477041250399594%;&quot; data-widthpercent=&quot;49.05&quot; data-is-animation=&quot;false&quot; data-origin-height=&quot;659&quot; data-origin-width=&quot;1116&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TDMOo/dJMcaiCVmCC/NGdad1FN0ejEY8biRlFBOK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTDMOo%2FdJMcaiCVmCC%2FNGdad1FN0ejEY8biRlFBOK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1116&quot; height=&quot;659&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;위의 사진은 스너버 커패시터의 전선 길이를 30cm로 의도적으로 길게 배치하였을 때 스위칭 파형입니다. 전선의 길이가 길면 인덕턴스가 늘어나고 에너지 흡수율이 낮아집니다. 스너버가 없을때보다는 개선된 파형으로 보이지만, 최대한 가까이 배치할 수록 그 효과는 커집니다.&lt;br /&gt;&lt;br /&gt;하지만, 서지에서 발생하는 에너지를 스너버커패시터에서 소모하는 개념으로 서지 전압 감소에 기여하지만, 손실 감소에는 기여하지 않습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;결론적으로, 위의 실험들로 다음과 같은 결론을 얻었습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;스너버 커페시터의 배치로 Drain-Source의 서지 전압 감소가 가능하다. 스너버 커페시터는 필름커페시터를 사용한다.&lt;/li&gt;
&lt;li&gt;스너버 커페시터는 커페시터의 Drain에 최대한 가깝게 배치한다. 멀리할 수록 그 서지 감소 성능은 저하한다.&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>전력전자/인버터</category>
      <author>네 말이 옳다</author>
      <guid isPermaLink="true">https://he823.tistory.com/5</guid>
      <comments>https://he823.tistory.com/5#entry5comment</comments>
      <pubDate>Sat, 25 Apr 2026 17:11:37 +0900</pubDate>
    </item>
    <item>
      <title>#1 MAVSDK 환경구성 및 Offboard 예제</title>
      <link>https://he823.tistory.com/7</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이전 게시글에서 PX4 Autopilot의 개발환경을 구축하였습니다. &lt;br /&gt;이번 게시글에서는 MAVSDK를 이용해 Simulation 환경에서 드론을 비행하는 방법에 대해서 알아보겠습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. PX4 Autopilot Setup&lt;span&gt;&amp;nbsp;&lt;/span&gt;- MAVSDK&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MAVSDK는 MAVLINK 시스템을 사용하는 드론, 지상국 시스템과 상호작용 하기 위해서 사용하는 SDK입니다.&lt;br /&gt;&lt;br /&gt;mavsdk를 설치하겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1776494013283&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip3 install mavsdk&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #2c3e50; text-align: start;&quot;&gt;PX4를 사용한 드론은 MAVLINK 프로토콜을 이용해 통신합니다.&lt;br /&gt;그래서 사용자가 &quot;Arm&quot;라는 MAVLINK 프로토콜을 드론에게 전송하면&amp;nbsp; 드론은 시동을 걸게 됩니다.&lt;br /&gt;MAVLINK 프로토콜 기반으로 코드를 작성하면 원하는 대로 드론을 작동시킬 수 있습니다.&lt;br /&gt;&lt;br /&gt;하지만, 드론은 기체 상태에 따라 &quot;비행 가능&quot;과 &quot;불가능&quot;을 판단하고 동작을 거부할 수 있습니다.&lt;br /&gt;MAVLINK 프로토콜을 기반으로 코드를 작성하면, 드론의 상태를 계속해서 보내줘야 합니다.&lt;br /&gt;연결상태, 메시지 타입 등.. 많은 부분에 대해서 알고 일일이 코드로 작성해야 합니다.&lt;br /&gt;하지만, MAVSDK를 사용하면 SDK가 이를 처리해 복잡도를 줄일 수 있고 간결한 코드 작성이 가능합니다.&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #2c3e50; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. MAVSDK vs MAVLink&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #2c3e50;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;가령, &lt;br /&gt;Arm -&amp;gt; 3m로 상승 -&amp;gt; 대기 -&amp;gt; 착륙 &lt;br /&gt;이라는 명령을 시행한다고 합시다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #2c3e50;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;MAVlink 프로토콜로 해당 코드를 작성한다면,&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #2c3e50; text-align: start;&quot;&gt;Arming 명령을 Parameter로 정리해야 하고, Arming 명령이 제대로 들어갔는지 ack로 확인도 해줘야 합니다. &lt;br /&gt;하지만, MAVSDK로 코드를 작성하면, 아래와 같이 간결해집니다.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1776492325571&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import asyncio

from mavsdk import System

async def run():
    drone = System()
    await drone.connect(system_address=&quot;udpin://0.0.0.0:14540&quot;)

    async for state in drone.core.connection_state():
        if state.is_connected:
            print(&quot;Connected&quot;)
            break

    async for health in drone.telemetry.health():
        if health.is_global_position_ok and health.is_home_position_ok:
            print(&quot;-- Global position estimate OK&quot;)
            break
 
    await drone.action.set_takeoff_altitude(3.0) # 3.0m까지 상승

    await drone.action.arm() # 시동 걸기

    await drone.action.takeoff() # 이륙 하기

    await asyncio.sleep(15) # 비행부터(시동부터) 15초까지 대기하기

    await drone.action.land() # 착륙하기

if __name__ == &quot;__main__&quot;:
    # Run the asyncio loop
    asyncio.run(run())&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #2c3e50;&quot;&gt;&lt;span style=&quot;color: #2c3e50;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;실제 arm, takeoff, land까지 단 5줄 만에 코드 작성이 끝났습니다.&lt;br /&gt;MAVlink 프로토콜을 직접 정의해서 코드를 작성할 때보다 매우 간결해진 모습을 볼 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>드론/PX4</category>
      <author>네 말이 옳다</author>
      <guid isPermaLink="true">https://he823.tistory.com/7</guid>
      <comments>https://he823.tistory.com/7#entry7comment</comments>
      <pubDate>Sat, 25 Apr 2026 16:48:26 +0900</pubDate>
    </item>
    <item>
      <title>#3 인버터 구동 - PWM 출력을 위한 TMS320F28335 레지스터 설정(2)</title>
      <link>https://he823.tistory.com/4</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이전 게시글에서 Ti의 MCU 인 TMS320F28335의 ePWM Submodule에 대해서 설명했습니다.&lt;br /&gt;TB, CC, AQ에 이어서 DB와 인버터 제작을 위한 카운터 설정에 대해서 알아보겠습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. ePWM Submodule - Deadband(DB)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인버터에서 중요한 Deadband입니다.&lt;br /&gt;인버터는 Highside와 Lowside FET가 각각 상보적으로 작동합니다. High가 On이면, Low가 Off인 상태로 작동하죠.&lt;br /&gt;그런데, 만약 Highside가 Low에서 High로 변화하는 순간 Lowside가 High이면 어떻게 될까요??&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;536&quot; data-origin-height=&quot;556&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1xJFW/dJMcagd4bRa/9Le9nKaXgVQKGjkac75UiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1xJFW/dJMcagd4bRa/9Le9nKaXgVQKGjkac75UiK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1xJFW/dJMcagd4bRa/9Le9nKaXgVQKGjkac75UiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1xJFW%2FdJMcagd4bRa%2F9Le9nKaXgVQKGjkac75UiK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;363&quot; height=&quot;377&quot; data-origin-width=&quot;536&quot; data-origin-height=&quot;556&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 FET가 소손되게 됩니다. 이를 방지하기 위해 Highside와 Lowside가 스위칭되기 전 시간적 여유가 필요합니다. &lt;br /&gt;서로의 간격을 두고 On, Off를 해야 안전합니다.&lt;br /&gt;이를 위해 간격을 설정하는 레지스터가 Deadband 모듈입니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1035&quot; data-origin-height=&quot;957&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bF0jLN/dJMcaf7gDS1/6XMnKZHRZTgo6bBaGBOeMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bF0jLN/dJMcaf7gDS1/6XMnKZHRZTgo6bBaGBOeMk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bF0jLN/dJMcaf7gDS1/6XMnKZHRZTgo6bBaGBOeMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbF0jLN%2FdJMcaf7gDS1%2F6XMnKZHRZTgo6bBaGBOeMk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;757&quot; height=&quot;700&quot; data-origin-width=&quot;1035&quot; data-origin-height=&quot;957&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실질적 마지막 단계의 Submodule입니다. 이후 GPIO에 출력된다 생각하시면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;850&quot; data-origin-height=&quot;372&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/M6tlm/dJMcagLUv1a/Yk5wkCiRBinM4FeT0ytkNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/M6tlm/dJMcagLUv1a/Yk5wkCiRBinM4FeT0ytkNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/M6tlm/dJMcagLUv1a/Yk5wkCiRBinM4FeT0ytkNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FM6tlm%2FdJMcagLUv1a%2FYk5wkCiRBinM4FeT0ytkNK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;850&quot; height=&quot;372&quot; data-origin-width=&quot;850&quot; data-origin-height=&quot;372&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RED로 Rising Edge에서, FED로 Falling Edge에서 딜레이를 줄 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1241&quot; data-origin-height=&quot;815&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dGsqYr/dJMcaflU5n9/0YsIysiDBxVWiKGViJUQjk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dGsqYr/dJMcaflU5n9/0YsIysiDBxVWiKGViJUQjk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dGsqYr/dJMcaflU5n9/0YsIysiDBxVWiKGViJUQjk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdGsqYr%2FdJMcaflU5n9%2F0YsIysiDBxVWiKGViJUQjk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1241&quot; height=&quot;815&quot; data-origin-width=&quot;1241&quot; data-origin-height=&quot;815&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IN_MODE를 11로 설정하면 라이징과 폴링엣지에서 모두 딜레이를 줄 수 있습니다.&lt;br /&gt;POLSEL을 11로 설정하면 EPWMxA와 EPWMxB가 서로 상보적으로 동작하게 해 줍니다. 그러면 AQ모델에서 EPWMxA와 EPWMxB의 설정이 하나로 통합됩니다.&lt;br /&gt;OUT_MODE를 11로 설정하면 A와 B모두 딜레이를 준 상태로 출력해주는 역할을 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하강 지연시간과 상승지연시간의 공식은&lt;br /&gt;$DBFED \times T_{TBCLK}$, $DBRED \times T_{TBCLK}$&lt;br /&gt;입니다. 저는 &lt;b&gt;0.66us&lt;/b&gt;로 설정할 것이기 때문에 &lt;b&gt;100&lt;/b&gt;으로 각각 설정해주겠습니다.&lt;br /&gt;$$ 100 / (150*10^-6) = 0.66us$$&lt;br /&gt;&lt;br /&gt;이를 코드로 표현한다면&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;EPwmRegs-&amp;gt;DBCTL.bit.IN_MODE=0X0;

EPwm1Regs.DBCTL.bit.POLSEL=0X2; //사용할 PWM중 xB를 A에 반전시킨다.
EPwm3Regs.DBCTL.bit.POLSEL=0X2;
EPwm6Regs.DBCTL.bit.POLSEL=0X2;

EPwm1Regs.DBCTL.bit.OUT_MODE=0X3; // 출력을 낼 PWM을 설정한다.
EPwm3Regs.DBCTL.bit.OUT_MODE=0X3;
EPwm6Regs.DBCTL.bit.OUT_MODE=0X3;

EPwmRegs-&amp;gt;DBRED=100;
EPwmRegs-&amp;gt;DBFED=100;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. SPWM 출력을 위한 레지스터 출력값 설정&lt;br /&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;573&quot; data-origin-height=&quot;280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mElFq/dJMcacbEv4r/dDeeOhFI9KhXP0A7CYqaB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mElFq/dJMcacbEv4r/dDeeOhFI9KhXP0A7CYqaB1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mElFq/dJMcacbEv4r/dDeeOhFI9KhXP0A7CYqaB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmElFq%2FdJMcacbEv4r%2FdDeeOhFI9KhXP0A7CYqaB1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;573&quot; height=&quot;280&quot; data-origin-width=&quot;573&quot; data-origin-height=&quot;280&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 글에서 Triangular Wave는 0에서 TBPRD까지 움직이는 카운터와 같고 Reference signal은 CMPA와 같다고 말씀드렸습니다. &lt;br /&gt;그러면 TBPRD를 이용해 인버터의 스위칭 주파수(20kHz)를 설정하고 CMPA에 정현파(60Hz)를 넣어주면 SPWM signal을 출력할 수 있게 됩니다.&lt;/p&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;#define M_PI 3.141592
#define freq 60.0
Tsamp = 0.00005; //샘플링 주기 설정
time += Tsamp; // 코드 한바퀴 돌 때마다 샘플링 주기만큼 +됨
Theta1 = (2 * M_PI * freq * time); //a상
Theta2 = (2* M_PI * freq * time)-(2.0/3.0)*M_PI;
Theta3 = (2* M_PI * freq * time)+(2.0/3.0)*M_PI;

 if(Theta1 &amp;gt; 2*M_PI) time = 0;
 sine1 = sin(Theta1)*3750.0*0.5 + 3750*0.5;
 sine2 = sin(Theta2)*3750.0*0.5 + 3750*0.5;
 sine3 = sin(Theta3)*3750.0*0.5 + 3750*0.5;
    
 EPwm1Regs.CMPA.half.CMPA = sine1;
 EPwm3Regs.CMPA.half.CMPA = sine2;
 EPwm6Regs.CMPA.half.CMPA = sine3;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 방식으로 ePWM 1,3,6번에 정현파를 출력할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1549&quot; data-origin-height=&quot;617&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mVtdG/dJMcaippE5X/CwGKXwO5CCHsbcowoMmZx1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mVtdG/dJMcaippE5X/CwGKXwO5CCHsbcowoMmZx1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mVtdG/dJMcaippE5X/CwGKXwO5CCHsbcowoMmZx1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmVtdG%2FdJMcaippE5X%2FCwGKXwO5CCHsbcowoMmZx1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1549&quot; height=&quot;617&quot; data-origin-width=&quot;1549&quot; data-origin-height=&quot;617&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PSIM으로 C코드를 이용해서 출력 결과 파형입니다.&lt;/p&gt;</description>
      <category>전력전자/인버터</category>
      <author>네 말이 옳다</author>
      <guid isPermaLink="true">https://he823.tistory.com/4</guid>
      <comments>https://he823.tistory.com/4#entry4comment</comments>
      <pubDate>Sun, 19 Apr 2026 11:48:07 +0900</pubDate>
    </item>
    <item>
      <title>#2 인버터 구동 - PWM 출력을 위한 TMS320F28335 레지스터 설정(1)</title>
      <link>https://he823.tistory.com/3</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;인버터를 구동하기 위해서는 0~5V의 PWM을 게이트드라이버에 인가해야 하고 이를 게이트 드라이버를 통해 0-18V로 승압하는 과정을 거쳐야 한다고 이전 게시글에서 설명해 드렸습니다.&lt;br /&gt;이번 글에서는 MCU를 이용해 어떤 방식으로 PWM을 발생하고, 인버터에 SPWM을 이용해 입력하는지에 대해서 설명하도록 하겠습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. TMS320F28335 기능 설명 - ePWM(Enhanced Pulse Width Modulator Module )&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ti사의 MCU인 TMS320F28335에는 ePWM을 통해 PWM 출력이 가능합니다.&lt;br /&gt;ePWM을 쉽게 설명하자면, &lt;b&gt;다양한 기능을 가진 PWM발생 장치&lt;/b&gt;라 생각하면 좋습니다.&lt;br /&gt;정말 다양한 기능을 가지고 있기 때문에 서브모듈별로 기능과 동작방식을 을 자세히 알아두어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Submodule을 살펴보기 전, 인버터 개요에서 설명한 내용을 잠시 봅시다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;573&quot; data-origin-height=&quot;280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cktVCw/dJMcai3WQWc/m5P5il5sDZPhxnS6hOAVJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cktVCw/dJMcai3WQWc/m5P5il5sDZPhxnS6hOAVJK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cktVCw/dJMcai3WQWc/m5P5il5sDZPhxnS6hOAVJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcktVCw%2FdJMcai3WQWc%2Fm5P5il5sDZPhxnS6hOAVJK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;573&quot; height=&quot;280&quot; data-origin-width=&quot;573&quot; data-origin-height=&quot;280&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;SPWM을 구현하려면, 삼각파 형태의 Triangular wave와 정현파 형태의 Reference Signal이 필요하다고 말씀드렸습니다.&lt;br /&gt;MCU는 일반적으로 Timer를 기반으로 PWM을 출력합니다.&lt;br /&gt;그러면 MCU는 어떻게 Timer를 이용해 삼각파와 정현파를 발생하고, 이를 비교기에 넣어 PWM을 출력할까요?&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2-1. ePWM Submodule - Time-base&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 위쪽에 있는 Time-base 모듈을 살펴보겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1224&quot; data-origin-height=&quot;949&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cOKWw8/dJMcaadQOUm/lxQ1mzMO07V3M47IKYsbnk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cOKWw8/dJMcaadQOUm/lxQ1mzMO07V3M47IKYsbnk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cOKWw8/dJMcaadQOUm/lxQ1mzMO07V3M47IKYsbnk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcOKWw8%2FdJMcaadQOUm%2FlxQ1mzMO07V3M47IKYsbnk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1224&quot; height=&quot;949&quot; data-origin-width=&quot;1224&quot; data-origin-height=&quot;949&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1866&quot; data-origin-height=&quot;757&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l2eQS/dJMcadauUE4/kswiM71NMR2emOsA8MgcbK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l2eQS/dJMcadauUE4/kswiM71NMR2emOsA8MgcbK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l2eQS/dJMcadauUE4/kswiM71NMR2emOsA8MgcbK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl2eQS%2FdJMcadauUE4%2FkswiM71NMR2emOsA8MgcbK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1866&quot; height=&quot;757&quot; data-origin-width=&quot;1866&quot; data-origin-height=&quot;757&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 기능을 숙지하면 좋지만, 인버터 설계를 위한 주요 기능을 살펴봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TB는 다음 기능을 수행합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Time-base clock의 스케일을 조정합니다(system clock이랑 연관되어 있음)&lt;/li&gt;
&lt;li&gt;PWM의 time base counter의 주파수와 주기를 설정합니다.&lt;/li&gt;
&lt;li&gt;PWM의 모드를 설정합니다 &amp;rarr; SPWM, SVPWM의 경우에는 Count up-down mode를 사용합니다.&lt;/li&gt;
&lt;li&gt;Phase를 설정합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1378&quot; data-origin-height=&quot;1003&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yKYW5/dJMcadIlYaY/g1s88s6KlS4gkofkkzQm50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yKYW5/dJMcadIlYaY/g1s88s6KlS4gkofkkzQm50/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yKYW5/dJMcadIlYaY/g1s88s6KlS4gkofkkzQm50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyKYW5%2FdJMcadIlYaY%2Fg1s88s6KlS4gkofkkzQm50%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1378&quot; height=&quot;1003&quot; data-origin-width=&quot;1378&quot; data-origin-height=&quot;1003&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 맨 아래의 TBCLK를 살펴봅시다.&lt;br /&gt;시스템 클럭(SYSCLKOUT)과 TBCTL레지스터의 설정값에 의해 분주비가 설정되어 TBCLK(Time-base Submodule을 위한 클럭)가 생성되어 TBCTR을 구동합니다.&lt;br /&gt;TBCTR(카운터값)은 TBCLK의 입력을 받아 Count UP, DOWN, UP-DOWN모드에 따라 증가하거나 감소하면서 TBPRD에 도달합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1433&quot; data-origin-height=&quot;686&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2Bz8c/dJMcacQfPVA/ZckYeTdbzWGYxENm1KMGwk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2Bz8c/dJMcacQfPVA/ZckYeTdbzWGYxENm1KMGwk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2Bz8c/dJMcacQfPVA/ZckYeTdbzWGYxENm1KMGwk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2Bz8c%2FdJMcacQfPVA%2FZckYeTdbzWGYxENm1KMGwk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1433&quot; height=&quot;686&quot; data-origin-width=&quot;1433&quot; data-origin-height=&quot;686&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TBCTR(카운터값)은 UP-DOWN Count Mode로 작동시키면 0에서 시작해서 TBPRD까지 상승하고, 다시 0으로 이동합니다.&lt;br /&gt;즉, 삼각파형태로 만들 수 있게 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6Buaq/dJMcagrz1Sq/C9btddTwX8zACGpK0xInhK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6Buaq/dJMcagrz1Sq/C9btddTwX8zACGpK0xInhK/img.png&quot; data-origin-width=&quot;1168&quot; data-origin-height=&quot;366&quot; data-is-animation=&quot;false&quot; style=&quot;width: 60.2203%; margin-right: 10px;&quot; data-widthpercent=&quot;60.93&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6Buaq/dJMcagrz1Sq/C9btddTwX8zACGpK0xInhK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6Buaq%2FdJMcagrz1Sq%2FC9btddTwX8zACGpK0xInhK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1168&quot; height=&quot;366&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cktVCw/dJMcai3WQWc/m5P5il5sDZPhxnS6hOAVJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cktVCw/dJMcai3WQWc/m5P5il5sDZPhxnS6hOAVJK/img.png&quot; data-origin-width=&quot;573&quot; data-origin-height=&quot;280&quot; data-is-animation=&quot;false&quot; style=&quot;width: 38.6169%;&quot; data-widthpercent=&quot;39.07&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cktVCw/dJMcai3WQWc/m5P5il5sDZPhxnS6hOAVJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcktVCw%2FdJMcai3WQWc%2Fm5P5il5sDZPhxnS6hOAVJK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;573&quot; height=&quot;280&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인버터는 스위칭 주파수가 존재합니다. 만약, 20kHz의 스위칭 주파수가 필요하면&lt;br /&gt;이 &lt;b&gt;Triangular wave의 주파수를 20kHz&lt;/b&gt;로 만들어주면 되는 것이고,&lt;br /&gt;이는 결국 &lt;b&gt;카운터를&lt;/b&gt; &amp;nbsp;&lt;b&gt;UP-DOWN Count Mode&lt;/b&gt;로 작동해 &lt;b&gt;TBCLK&lt;/b&gt;와 &lt;b&gt;TBPRD&lt;/b&gt;를 적절히 조합하여 &lt;b&gt;&amp;nbsp;20kHz의 주파수의 삼각파로&lt;/b&gt;&amp;nbsp;만들어주면 되는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$TBCLK = SYSCLKOUT / (HSPCLKDIV \times CLKDIV)$&lt;br /&gt;HSPCLKDIV의 레지스터를 0x0으로 설정하면 1로 동작합니다.&lt;br /&gt;CLKDIV도 0x0으로 설정하면 1로 동작합니다. 즉, &lt;b&gt;TBCLK&lt;/b&gt;는 &lt;b&gt;150MHz&lt;/b&gt; 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$ (1/150MHz) \times 3750 \times 2 = 20,000$&lt;br /&gt;필요한 &lt;b&gt;TBPRD&lt;/b&gt;는 &lt;b&gt;3750&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 설명을 코드로 정리하면 다음과 같습니다.&lt;/p&gt;
&lt;pre class=&quot;xl&quot;&gt;&lt;code&gt;EPwmRegs-&amp;gt;TBCTL.bit.HSPCLKDIV = 0x0;
EPwmRegs-&amp;gt;TBCTL.bit.CLKDIV = 0x0;
EPwmRegs-&amp;gt;TBPRD = 3750;
EPwmRegs-&amp;gt;TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; //0x2&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2-2. ePWM Submodule - Counter-Compare(CC)&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1468&quot; data-origin-height=&quot;788&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dhzxsR/dJMcacpbXyh/lVKDK2PkyEe9lvHL7WUcCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dhzxsR/dJMcacpbXyh/lVKDK2PkyEe9lvHL7WUcCk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dhzxsR/dJMcacpbXyh/lVKDK2PkyEe9lvHL7WUcCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdhzxsR%2FdJMcacpbXyh%2FlVKDK2PkyEe9lvHL7WUcCk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;678&quot; height=&quot;364&quot; data-origin-width=&quot;1468&quot; data-origin-height=&quot;788&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과만 살펴보면, TB모듈에서 값을 받아와서 CMPA와 CMPB를 출력하는 역할을 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;573&quot; data-origin-height=&quot;280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LXM99/dJMcajaJQt8/1B2LFIkYOhORXmxLNRXR0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LXM99/dJMcajaJQt8/1B2LFIkYOhORXmxLNRXR0k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LXM99/dJMcajaJQt8/1B2LFIkYOhORXmxLNRXR0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLXM99%2FdJMcajaJQt8%2F1B2LFIkYOhORXmxLNRXR0k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;573&quot; height=&quot;280&quot; data-origin-width=&quot;573&quot; data-origin-height=&quot;280&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TB에서 Triangular wave를 생성할 수 있었다면 &lt;br /&gt;CC에서 Reference signal을 생성할 수 있습니다.&lt;br /&gt;인버터는 60Hz의 주파수를 가져야 하므로&lt;b&gt; 60Hz의 정현파&lt;/b&gt;를 출력하는 &lt;b&gt;reference signal&lt;/b&gt;을 만들어내면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1857&quot; data-origin-height=&quot;507&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cIYeqP/dJMcabRkYr7/Ziv24me7UCjI1iZZ4ItqTK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cIYeqP/dJMcabRkYr7/Ziv24me7UCjI1iZZ4ItqTK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cIYeqP/dJMcabRkYr7/Ziv24me7UCjI1iZZ4ItqTK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcIYeqP%2FdJMcabRkYr7%2FZiv24me7UCjI1iZZ4ItqTK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1857&quot; height=&quot;507&quot; data-origin-width=&quot;1857&quot; data-origin-height=&quot;507&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CC에는 CMPA와 CMPB가 존재하는데 인버터의 경우 Highside와 Lowside가 각각 상보적으로 동작합니다. &lt;br /&gt;즉, 두 Signal이 완벽한 반대이죠.&lt;br /&gt;상보적으로 입력되는 신호 중 하나가 CMPA고 다른 하나는 CMPB입니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1924&quot; data-origin-height=&quot;1049&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cik9Wp/dJMcad2D9vb/Xkxfu9KLKibD60hc8fTRE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cik9Wp/dJMcad2D9vb/Xkxfu9KLKibD60hc8fTRE1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cik9Wp/dJMcad2D9vb/Xkxfu9KLKibD60hc8fTRE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcik9Wp%2FdJMcad2D9vb%2FXkxfu9KLKibD60hc8fTRE1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1924&quot; height=&quot;1049&quot; data-origin-width=&quot;1924&quot; data-origin-height=&quot;1049&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;삼각파가 존재하고, 그에 맞춘 CMPA와 CMPB의 동작 예시 설명입니다. 정말 예시를 위한 예시파형이므로 실제론 이렇게 사용하지 않는다는 것만 알아두면 될 것 같습니다.&lt;br /&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;먼저 CMPB가 삼각파를 만나는 첫 지점에서 펄스(CTR = CMPB)가 발생합니다. CMPA가 삼각파를 만나는 지점에서도 펄스가 발생(CTR = CMPA)합니다. 하강하는 삼각파에서도 똑같은 방식으로 펄스가 발생합니다. 그러면, 이 지점에서 무슨 활동을 할지, 결정해 주는 것이 필요합니다. PWM을 발생할지 아니면 발생 안 할지 High로 설정할지 Low로 설정할지 등등.. 펄스마다 무슨 활동을 할 것인지에 대한 정의가 필요합니다. 그 정의를 하는 것이 AQ모델입니다.&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2-3. ePWM Submodule -&amp;nbsp; Action-Qualifier (AQ)&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1165&quot; data-origin-height=&quot;578&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kRHUB/dJMcadBx6OR/XMc8UHk4X6KtNGhO3tine0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kRHUB/dJMcadBx6OR/XMc8UHk4X6KtNGhO3tine0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kRHUB/dJMcadBx6OR/XMc8UHk4X6KtNGhO3tine0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkRHUB%2FdJMcadBx6OR%2FXMc8UHk4X6KtNGhO3tine0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1165&quot; height=&quot;578&quot; data-origin-width=&quot;1165&quot; data-origin-height=&quot;578&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과만 보면, EPWMxA와 EPWMxB의 동작을 DB로 넘겨주는 역할을 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1757&quot; data-origin-height=&quot;632&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbQeOD/dJMcajhva2i/ZKPu5nkAowmEQQPGe8wCWK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbQeOD/dJMcajhva2i/ZKPu5nkAowmEQQPGe8wCWK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbQeOD/dJMcajhva2i/ZKPu5nkAowmEQQPGe8wCWK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbQeOD%2FdJMcajhva2i%2FZKPu5nkAowmEQQPGe8wCWK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1757&quot; height=&quot;632&quot; data-origin-width=&quot;1757&quot; data-origin-height=&quot;632&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각각의 펄스에서 무슨 활동을 할지 설정할 수 있습니다. 인버터 설계를 위해선 SET HIGH와 CLEAR LOW만 보면 됩니다.&lt;br /&gt;즉, PWM HIGH를 출력할지 LOW를 출력할지 결정한다는 뜻입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1826&quot; data-origin-height=&quot;483&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mVpjg/dJMb99MJv1g/TbrgkS3SFSaemb5hwgykFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mVpjg/dJMb99MJv1g/TbrgkS3SFSaemb5hwgykFK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mVpjg/dJMb99MJv1g/TbrgkS3SFSaemb5hwgykFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmVpjg%2FdJMb99MJv1g%2FTbrgkS3SFSaemb5hwgykFK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1826&quot; height=&quot;483&quot; data-origin-width=&quot;1826&quot; data-origin-height=&quot;483&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상승할 때와 하강할 때의 역할을 각각 부여할 수 있는데, 이는 CAU, CBU에서 업카운트, CAD, CBD에 다운카운트에서 역할을 부여할 수 있습니다. &lt;br /&gt;&lt;br /&gt;상보적 PWM출력을 위해선 &lt;br /&gt;업카운트에서 카운터가 CMPA를 만날 경우 PWM은 LOW를 출력하고, 다운카운트에 CMPA를 만날 경우 High를 출력하면 되고&lt;br /&gt;반대로 CMPB는 업카운트에서 High, 다운카운트에서 Low를 출력하면 됩니다. &lt;br /&gt;&lt;br /&gt;예시 상황에서 이를 그림으로 그려보면&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;570&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cyk3Sy/dJMcaiv8Jbu/VCcmKIXFo6lm79xKVXQSQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cyk3Sy/dJMcaiv8Jbu/VCcmKIXFo6lm79xKVXQSQK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cyk3Sy/dJMcaiv8Jbu/VCcmKIXFo6lm79xKVXQSQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcyk3Sy%2FdJMcaiv8Jbu%2FVCcmKIXFo6lm79xKVXQSQK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2048&quot; height=&quot;570&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;570&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 표현되고 이를 코드로 옮겨본다면&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;#define	AQ_CLEAR		0x1
#define	AQ_SET			0x2

EPwmRegs-&amp;gt;AQCTLA.bit.CAU = AQ_CLEAR; 
EPwmRegs-&amp;gt;AQCTLA.bit.CAD = AQ_SET;
EPwmRegs-&amp;gt;AQCTLB.bit.ZAU = AQ_SET; 
EPwmRegs-&amp;gt;AQCTLB.bit.CBU = AQ_CLEAR;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 같이 표현할 수 있습니다.&lt;/p&gt;</description>
      <category>전력전자/인버터</category>
      <author>네 말이 옳다</author>
      <guid isPermaLink="true">https://he823.tistory.com/3</guid>
      <comments>https://he823.tistory.com/3#entry3comment</comments>
      <pubDate>Sun, 19 Apr 2026 01:21:45 +0900</pubDate>
    </item>
  </channel>
</rss>